2011-10-10 9 views

risposta

6

Ti piace questa:

range = 1..5 
store = 0 

range.each_with_index do |value, i| 
    next_value = range.to_a[i+1].nil? ? 0 : range.to_a[i+1] 
    store += value + next_value 
end  

p store # => 29 

Ci possono essere modi migliori, ma questo funziona.

È possibile ottenere la successiva del valore successivo in questo modo:

range.to_a[i+2] 
+1

Questo codice si interromperà se l'intervallo fosse cambiato, come per '11..15': darebbe 65 quando dovrebbe dare 119. –

+0

bello! grazie per la tua risposta veloce! A pensarci bene, @AndrewGrimm aveva ragione. – jovhenni19

+0

@AndrewGrimm, hai ragione, lascia che lo aggiusti. – Mischa

1

Un approccio che non sarebbe utilizzare gli indici è Enumerable # zip:

range = 11..15 
store = 0 # This is horrible imperative programming 
range.zip(range.to_a[1..-1], range.to_a[2..-1]) do |x, y, z| 
    # nil.to_i equals 0 
    store += [x, y, z].map(&:to_i).inject(:+) 
end 
store 
10

Fin dal Ruby 1.8.7, il Il modulo enumerabile ha avuto un metodo each_cons che fa quasi esattamente quello che vuoi:

each_cons (n) {...} → nil
each_cons (n) → an_enumerator

Itera il blocco specificato per ciascuna serie di consecutivi <n> elementi. Se non viene fornito alcun blocco, restituisce un enumeratore.

es .:

(1..10).each_cons(3) { |a| p a } 
# outputs below 
[1, 2, 3] 
[2, 3, 4] 
[3, 4, 5] 
[4, 5, 6] 
[5, 6, 7] 
[6, 7, 8] 
[7, 8, 9] 
[8, 9, 10] 

L'unico problema è che non ripete l'ultimo elemento. Ma è banale da sistemare. In particolare, si vuole

store = 0 
range = 1..5 

range.each_cons(2) do |i, next_value_of_i| 
    store += i + next_value_of_i 
end 
store += range.end 

p store # => 29 

Ma si potrebbe anche fare questo:

range = 1..5 

result = range.each_cons(2).reduce(:+).reduce(:+) + range.end 

p result # => 29 

In alternativa, si può trovare il seguente per essere più leggibile:

result = range.end + range.each_cons(2) 
          .reduce(:+) 
          .reduce(:+) 
Problemi correlati