Czy mogę zdefiniować przesunięcie indeksu w iteratorze pętli each_with_index? Moja prosta próba nie powiodła się:
some_array.each_with_index{|item, index = 1| some_func(item, index) }
Edytować:
Wyjaśnienie: nie chcę przesunięcia tablicy Chcę, aby indeks w ramach each_with_index nie zaczynał się od 0, ale np. 1.
Odpowiedzi:
Właściwie
Enumerator#with_index
otrzymuje przesunięcie jako opcjonalny parametr:[:foo, :bar, :baz].to_enum.with_index(1).each do |elem, i| puts "#{i}: #{elem}" end
wyjścia:
1: foo 2: bar 3: baz
Swoją drogą myślę, że jest tylko w 1.9.2.
źródło
with_index
brak parametrów, indeksy z0
Poniższy tekst jest zwięzły, używając klasy modułu wyliczającego Rubiego.
[:foo, :bar, :baz].each.with_index(1) do |elem, i| puts "#{i}: #{elem}" end
wynik
1: foo 2: bar 3: baz
Array # każdy zwraca moduł wyliczający, a wywołanie Enumerator # with_index zwraca inny moduł wyliczający, do którego przekazywany jest blok.
źródło
1) Najprościej jest podstawić
index+1
zamiastindex
funkcji:some_array.each_with_index{|item, index| some_func(item, index+1)}
ale prawdopodobnie nie tego chcesz.
2) Następną rzeczą, jaką możesz zrobić, jest zdefiniowanie innego indeksu
j
w bloku i użycie go zamiast oryginalnego indeksu:some_array.each_with_index{|item, i| j = i + 1; some_func(item, j)}
3) Jeśli chcesz często używać indeksu w ten sposób, zdefiniuj inną metodę:
module Enumerable def each_with_index_from_one *args, &pr each_with_index(*args){|obj, i| pr.call(obj, i+1)} end end %w(one two three).each_with_index_from_one{|w, i| puts "#{i}. #{w}"} # => 1. one 2. two 3. three
Aktualizacja
Ta odpowiedź, na którą odpowiedziano kilka lat temu, jest już nieaktualna. W przypadku nowoczesnych rubinów odpowiedź Zacka Xu będzie działać lepiej.
źródło
+1
w moim kodzie na+2
lub+10
. To też działa.Jeśli
some_index
jest w jakiś sposób sensowne, rozważ użycie skrótu zamiast tablicy.źródło
Wpadłem na to.
Moje rozwiązanie niekonieczne jest najlepsze, ale po prostu zadziałało.
W widoku iteracja:
po prostu dodaj: indeks + 1
To wszystko dla mnie, ponieważ nie używam żadnych odniesień do tych numerów indeksu, ale tylko po to, aby pokazać je na liście.
źródło
Tak, możesz
some_array[offset..-1].each_with_index{|item, index| some_func(item, index) } some_array[offset..-1].each_with_index{|item, index| some_func(item, index+offset) } some_array[offset..-1].each_with_index{|item, index| index+=offset; some_func(item, index) }
UPD
Powinienem również zauważyć, że jeśli przesunięcie jest większe niż rozmiar twojej tablicy, będzie to błąd. Dlatego:
some_array[1000,-1] => nil nil.each_with_index => Error 'undefined method `each_with_index' for nil:NilClass'
Co możemy tu zrobić:
(some_array[offset..-1]||[]).each_with_index{|item, index| some_func(item, index) }
Lub aby wstępnie zweryfikować przesunięcie:
offset = 1000 some_array[offset..-1].each_with_index{|item, index| some_func(item, index) } if offset <= some_array.size
To trochę hacky
UPD 2
O ile zaktualizowałeś swoje pytanie i teraz nie potrzebujesz przesunięcia tablicy, ale przesunięcia indeksu, więc rozwiązanie @sawa będzie działać dobrze dla Ciebie
źródło
Ariel ma rację. To najlepszy sposób, aby sobie z tym poradzić i nie jest tak źle
ary.each_with_index do |a, i| puts i + 1 #other code end
Jest to całkowicie akceptowalne i lepsze niż większość rozwiązań, które widziałem. Zawsze myślałem, że właśnie po to jest #inject ... no cóż.
źródło
Innym podejściem jest użycie
map
some_array = [:foo, :bar, :baz] some_array_plus_offset_index = some_array.each_with_index.map {|item, i| [item, i + 1]} some_array_plus_offset_index.each{|item, offset_index| some_func(item, offset_index) }
źródło
Działa to w każdej wersji ruby:
%W(one two three).zip(1..3).each do |value, index| puts value, index end
A dla ogólnej tablicy:
a.zip(1..a.length.each do |value, index| puts value, index end
źródło
offset = 2 some_array[offset..-1].each_with_index{|item, index| some_func(item, index+offset) }
źródło