2013-08-13 15 views
9

Questa è una domanda sulle convenzioni. I due gruppi di comandi seguenti restituiscono risultati identici.Convenzione ruby ​​per l'accesso al primo/ultimo elemento nell'array

a = [1, 2, 3] 

a.first # => 1 
a[0]  # => 1 

a.last # => 3 
a[-1] # => 3 

Quale di questi è preferito in Ruby, l'indice esplicito o le funzioni? Supponendo, naturalmente, che questo sia nel codice che sempre accede al primo o all'ultimo elemento.

Nota: ho pensato ai cicli che ciascuno avrebbe intrapreso. Poiché first e last accettano parametri, avranno un po 'più di overhead, ma non so se ciò influisce su ciò che la comunità preferisce.

Grazie!


EDIT

Se si leggono i commenti su questo post, ci fu un grande dibattito circa il mio ultimo paragrafo. Mentre non ero riuscito a ricordare che [x] è equivalente a .[](x), avevo ragione nella mia conclusione che il primo e l'ultimo hanno un po 'più di overhead. Considerando la natura di entrambi, credo che ciò sia dovuto alla verifica degli argomenti per first/last. Questi devono controllare se ci sono argomenti mentre [] può presumere che essi esistano.

CODICE

require 'benchmark' 

a = [1..1000] 

MAX = 1000000 

Benchmark.bm(15) do |b| 
    b.report("small first") { MAX.times do; a.first; end } 
    b.report("small [0]") { MAX.times do; a[0]; end } 
    b.report("small last") { MAX.times do; a.last; end } 
    b.report("small [-1]") { MAX.times do; a[-1]; end } 
end 

a = [1..100000000000] 

Benchmark.bm(15) do |b| 
    b.report("large first") { MAX.times do; a.first; end } 
    b.report("large [0]") { MAX.times do; a[0]; end } 
    b.report("large last") { MAX.times do; a.last; end } 
    b.report("large [-1]") { MAX.times do; a[-1]; end } 
end 

RISULTATI

     user  system  total  real 
small first  0.350000 0.000000 0.350000 ( 0.901497) 
small [0]   0.330000 0.010000 0.340000 ( 0.857786) 
small last  0.370000 0.000000 0.370000 ( 1.054216) 
small [-1]  0.370000 0.000000 0.370000 ( 1.137655) 
         user  system  total  real 
large first  0.340000 0.010000 0.350000 ( 0.897581) 
large [0]   0.320000 0.010000 0.330000 ( 0.889725) 
large last  0.350000 0.000000 0.350000 ( 1.071135) 
large [-1]  0.380000 0.000000 0.380000 ( 1.119587) 
+1

Credo sia la prima e l'ultima perché rende più facile la preparazione e il rubino è un linguaggio che deve essere letto. Inoltre rende più facile per le persone dare un'occhiata al tuo codice e sapere cosa stai facendo –

+2

Questa è probabilmente una questione di opinione più che "cosa è meglio", ma preferirei "prima" e "ultima" se è esattamente ciò che intendevo . Se sei davvero preoccupato per le prestazioni in tempo reale, Ruby probabilmente non è la tua migliore scelta di linguaggi di scripting. ;) – lurker

+1

Utilizziamo 'first' e' last' perché sono disponibili. Sono disponibili perché sono necessari molto più spesso. Altri accessors per le posizioni dell'array sono disponibili in Rails, ma non sono davvero così utili o leggibili e, sebbene le persone possano usarli, vediamo la notazione '[n]' più spesso. Non è molto più difficile leggere '[n]', ed è infinitamente più pratico in quanto sono facili da usare nei loop. –

risposta

9

TL; DR

codice viene letto più di quello che è scritto e first e last prendere meno sforzo, especialy per un programmatore meno esperti Ruby o qualcuno di un altro linguaggio di programmazione capire.


first e last sono di solito preferito, perché comunicano la vostra intenzione con un po 'pensare di meno. Mentre la maggior parte dei programmatori saprà immediatamente che questi sono gli stessi:

a.first 
a[0] 

Il primo si legge ancora più facilmente. Non c'è una differenza marcata in quanto è difficile da leggere, ma è lì.

last, tuttavia, è un altro problema. Accedendo all'indice 0 otterrai il primo elemento di un array in quasi tutte le lingue. Ma l'indicizzazione negativa è disponibile solo in alcune lingue e il suo utilizzo è spesso diverso. Se un programmatore C con una minima esperienza Rubino sta cercando di leggere il mio codice, che capiranno velocemente ?:

a.last 
a[-1] 

L'indice negativo probabilmente costringerà a fare una ricerca su Google.

+0

Avevo affrontato lo stesso quando ho avviato Ruby con lo stile 'a [-1]' ...:) :) –

+1

@Babai: Anch'io. Ecco perché è utile per i suoi usi più potenti (ad esempio 'a [0 ..- 1]') ma non per ottenere solo l'ultimo elemento. – Linuxios

+0

Un programmatore C farebbe anche una smorfia e penserebbe "Oh mio Dio, stanno leggendo dati casuali!" (dati all'indirizzo di a - sizeof (a)). –

2

Dal Matz progettato Rubino dopo un paio di altre lingue, penso che le convenzioni vengono da quelle altre lingue.

In Lisp, uno dei genitori di ispirazione di Ruby, si può usare qualcosa di simile ai metodi last e first quindi mi dico last e first è convention.

Uso solo veramente first e last. Vedo molti programmi là fuori che usano quei metodi ma alla fine è la tua scelta. Questo è il bello di Ruby;)

2

Dal punto di vista della velocità, per gli array più grandi, first e last sono più veloci di []. Per gli array più piccoli è il contrario.

Large Array:

array = (0..100000000).to_a 

t = Time.now 
10.times{array[0]} 
puts Time.now - t 
# => 0.000225356 

t = Time.now 
10.times{array.first} 
puts Time.now - t 
# => 2.9736e-05 

t = Time.now 
10.times{array[-1]} 
puts Time.now - t 
# => 7.847e-06 

t = Time.now 
10.times{array.last} 
puts Time.now - t 
# => 6.174e-06 

Piccolo matrice:

array = (0..100).to_a 

t = Time.now 
10.times{array[0]} 
puts Time.now - t 
# => 4.403e-06 

t = Time.now 
10.times{array.first} 
puts Time.now - t 
# => 5.933e-06 

t = Time.now 
10.times{array[-1]} 
puts Time.now - t 
# => 4.982e-06 

t = Time.now 
10.times{array.last} 
puts Time.now - t 
# => 5.411e-06 

Per facilità di scrittura/lettura, first e last può essere utilizzato senza argomenti, a differenza [], in modo che siano più semplici.

A volte, utilizzando first e last rende le cose più facili, mentre è difficile con []: per esempio, array.each_slice(3).map(&:first).

+0

Fornire test per verificare che 'first' e' last' siano più veloci. Intuitivamente, penserei che sarebbero più lenti. – screenmutt

+0

Possiamo vedere benchmark? Sono curioso;) – Linuxios

+0

Ho appena aggiunto dei punti di riferimento alla mia domanda. – screenmutt

Problemi correlati