różnica między each.with_index i each_with_index w Rubim?

94

Jestem naprawdę zdezorientowany różnicą między each.with_indexa each_with_index. Mają różne typy, ale w praktyce wydają się identyczne.

Stan
źródło
7
Pomijając drobną różnicą, że with_indexpozwala indeks początkowy offsetowej, with_indexna ogół korzystne, gdy używany w połączeniu z map, reduce, collect, itd. Krótko mówiąc, map.with_indexbrzmi lepiej niż each_with_index.map. W pewnym sensie, gdy jest używany z map, jest zastępstwem dla nieistniejącej map_with_indexmetody.
Cary Swoveland

Odpowiedzi:

173

with_indexMetoda pobiera opcjonalny parametr, aby zrównoważyć indeks początkowy. each_with_indexrobi to samo, ale nie ma opcjonalnego indeksu początkowego.

Na przykład:

[:foo, :bar, :baz].each.with_index(2) do |value, index|
    puts "#{index}: #{value}"
end

[:foo, :bar, :baz].each_with_index do |value, index|
    puts "#{index}: #{value}"
end

Wyjścia:

2: foo
3: bar
4: baz

0: foo
1: bar
2: baz
Blacktide
źródło
41

each_with_indexzostał wprowadzony do Rubiego wcześniej. with_indexzostał wprowadzony później:

  1. aby umożliwić szersze zastosowanie z różnymi modułami wyliczającymi.
  2. aby indeks zaczynał się od liczby innej niż 0.

Dziś użycie with_indexbyłoby lepsze z punktu widzenia ogólności i czytelności, ale z punktu widzenia przyspieszenia kodu,each_with_index przebiega nieco szybciej niż each.with_index.

Kiedy czujesz, że pojedynczą metodę można łatwo wyrazić za pomocą prostego łączenia kilku metod w łańcuch, zwykle jest tak, że pojedyncza metoda jest szybsza niż łańcuch. Jeśli chodzi o inny przykład, reverse_eachdziała szybciej niż reverse.each. Te metody mają powód do istnienia.

sawa
źródło
1
Aby być uczciwym, przesunięcie nie zmienia indeksu, po prostu dodaje liczbę do indeksu. Kiedy sprawdzisz indeks po rozmowie, zauważysz, że nie ma to wpływu. Dobre notatki jak zwykle, @sawa
vgoff
2
Nie sądzę, że perf powinno być inne (przynajmniej nie zasadniczo). W tym reverseprzykładzie reversezwraca inną tablicę, a nie moduł wyliczający. Jeśli zwrócił moduł wyliczający, nie powinien być wolniejszy z dobrą implementacją.
akostadinov