Не могат ли всички или повечето случаи на `each` да бъдат заменени с `map`?

Разликата между Enumerable#each и Enumerable#map е дали връща приемника или картографирания резултат. Връщането към приемника е тривиално и обикновено не е необходимо да продължавате верига от методи след each като each{...}.another_method (вероятно не съм виждал такъв случай. Дори ако искате да се върнете към приемника, можете да го направите с tap). Така че мисля, че всички или повечето случаи, в които се използва Enumerable#each, могат да бъдат заменени с Enumerable#map. Греша ли? Ако съм прав, каква е целта на each? map по-бавен ли е от each?

Редактиране: Знам, че има обичайна практика да се използва each, когато не се интересувате от върнатата стойност. Не ме интересува дали съществува такава практика, но ме интересува дали такава практика има смисъл освен от гледна точка на конвенцията.


person sawa    schedule 30.09.2012    source източник


Отговори (4)


Изборът между map или each трябва да се определя от желания краен резултат: нов масив или без нов масив. Резултатът от map може да бъде огромен и/или глупав:

p ("aaaa".."zzzz").map{|word| puts word} #huge and useless array of nil's
person steenslag    schedule 30.09.2012
comment
Ако е бавен, разбирам, че не трябва да го използвам, но защо е глупаво? Това изобщо не го разбирам. Ruby наследи от Lisp идеята, че всяка оценка връща стойност. - person sawa; 30.09.2012
comment
Резултатът от това map е масив с 456976 нула (puts връща нула). След като бъде създаден, той се изхвърля. Използването на each изобщо не би го създало, спестявайки памет. (Кодът е леко коригиран) - person steenslag; 30.09.2012
comment
Това питам. Независимо дали има разлика в производителността. - person sawa; 30.09.2012
comment
Това също е семантика. Друг човек, който чете вашия код, вероятно ще се чуди защо сте решили да използвате map и каква е била целта ви при използването му, когато всъщност нямаше такава. - person Andrew Marshall; 30.09.2012

Разликата между map и each е по-важна от това дали едното връща нов масив, а другото не. Важната разлика е в това как те съобщават вашето намерение.

Когато използвате each, вашият код казва "Правя нещо за всеки елемент." Когато използвате map, кодът ви казва „Създавам нов масив, като трансформирам всеки елемент“.

Така че, докато можете да използвате map вместо each, независимо от производителността, кодът сега ще лъже за намерението си за всеки, който го чете.

person Wayne Conrad    schedule 30.09.2012

Съгласен съм с казаното от теб. Enumerable#each просто връща оригиналния обект, на който е бил извикан, докато Enumerable#map задава текущия елемент, който се повтаря, на върнатата стойност на блока и след това връща нов обект с тези промени.

Тъй като Enumerable#each просто връща самия оригинален обект, той може да бъде много предпочитан пред map, когато става въпрос за случаи, когато трябва просто да итерирате или преминавате през елементи.

Всъщност Enumerable#each е прост и универсален начин за извършване на традиционна итерация на for цикъл и всеки от тях е много предпочитан пред for циклите в Ruby.

person Mithun Sasidharan    schedule 30.09.2012
comment
Честно казано, не се интересувам как другите хора предпочитат един метод пред друг. Интересувам се дали има смисъл да се използва по различен начин each. - person sawa; 30.09.2012

Можете да видите значителната разлика между map и each, когато съставяте тези изброявания.

Например трябва да получите нов масив с индекси в него:

array.each.with_index.map { |index, element| [index, element] }

Или например просто трябва да приложите някакъв метод към всички елементи в масива и да отпечатате резултата, без да променяте оригиналния масив:

m = 2.method(:+)

[1,2,3].each { |a| puts m.call(a) } #=> prints 3, 4, 5

И има много други примери, където разликата между each и map е важен ключ при писането на код във функционален стил.

person megas    schedule 30.09.2012