Array # each vs. Array # map

92
hash = { "d" => [11, 22], "f" => [33, 44, 55] }

# case 1
hash.map {|k,vs| vs.map {|v| "#{k}:#{v}"}}.join(",")
=> "d:11,d:22,f:33,f:44,f:55"

# case 2
hash.map {|k,vs| vs.each {|v| "#{k}:#{v}"}}.join(",")
=> "11,22,33,44,55"

Satu-satunya perbedaan adalah penggunaan kasus 1 vs.map, penggunaan kasus 2 vs.each.

Apa yang terjadi disini?

pengguna612308
sumber

Jawaban:

174

Array#each mengeksekusi blok yang diberikan untuk setiap elemen array, lalu mengembalikan array itu sendiri.

Array#map juga mengeksekusi blok yang diberikan untuk setiap elemen larik, tetapi mengembalikan larik baru yang nilainya adalah nilai kembalian dari setiap iterasi blok.

Contoh: asumsikan Anda memiliki array yang didefinisikan sebagai berikut:

arr = ["tokyo", "london", "rio"]

Kemudian coba jalankan each:

arr.each { |element| element.capitalize }
# => ["tokyo", "london", "rio"]

Perhatikan nilai yang dikembalikan hanyalah array yang sama. Kode di dalam eachblok dijalankan, tetapi nilai yang dihitung tidak dikembalikan; dan karena kode tersebut tidak memiliki efek samping, contoh ini tidak berfungsi.

Sebaliknya, memanggil metode larik akan mapmengembalikan larik baru yang elemennya adalah nilai kembalian dari setiap putaran menjalankan mapblok:

arr.map { |element| element.capitalize }
# => ["Tokyo", "London", "Rio"]
Zaitun
sumber
Jawaban sempurna untuk dipahami. Hanya .. Penafian: Jika Anda terlalu sering menggunakan nilai kembali dari fungsi peta, Anda berpotensi membuang banyak memori.
Imran Ahmad
33

The efek samping yang sama yang menambahkan beberapa kebingungan untuk reverse engineering Anda.

Ya, keduanya melakukan iterasi atas array (sebenarnya, atas apa pun yang bercampur di Enumerable ) tetapi map akan mengembalikan Array yang terdiri dari hasil blok sementara masing - masing hanya akan mengembalikan Array asli.

Nilai yang dikembalikan dari masing - masing hanyalah array asli dan jarang digunakan dalam kode Ruby tetapi map adalah salah satu alat fungsional yang paling penting .

Apa yang mapdilakukan adalah mengembalikan array yang berisi hasil dari blok atau metode bernama yang dilewatkan. Sebagai contoh:

    2.2.3 :001 > [:how, :now, :brown, :cow].map &:to_s
 => ["how", "now", "brown", "cow"]

Dalam hal ini saya tidak melewatkan satu blok tetapi hanya a Symbol, namun class Symbolobjek memiliki to_procmetode yang akan menghasilkan:

[:how.to_s, :now.to_s, ...]

BTW, Anda mungkin kesulitan menemukan dokumentasi karena map adalah metode di Enumerable sedangkan masing-masing (satu metode yang diperlukan oleh modul Enumerable ) adalah metode di Array .

Sebagai catatan trivia: implementasi peta didasarkan pada masing-masing .

DigitalRoss
sumber
13

Berikut adalah demo singkat tentang perbedaan peta dari masing-masing

a = ["a", "b", "c"];
#Array.map
p a.map {|item| "map_" + item}
#prints ["map_a", "map_b", "map_c"]

#Array.each
p a.each {|item| "map_" + item}
#prints ["a", "b", "c"]

Anda melihat bahwa peta pengembalian ["map_a", "map_b", "map_c"]sedangkan masing-masing hanya iterates tapi mengembalikan array asli: ["a", "b", "c"].

Jadi masing-masing digunakan untuk memproses array dan peta digunakan untuk melakukan sesuatu dengan array yang diproses.

Rima
sumber
4

.each mengembalikan larik yang sama yang Anda berikan pada awalnya:

[1,2,3].each { |i| i + 1 }
#=> [1,2,3]

.map mengembalikan Array baru dari hasil setiap panggilan blok:

[1,2,3].map { |i| i + 1 }
#=> [2,3,4]
pastullo
sumber
1

Array # setiap metode mengembalikan array yang sama

a = [1,2,3,4,5]
a.object_id #70284994490700

b = a.each {|n| n + 2}
p b #[1,2,3,4,5]
b.object_id #70284994490700 <<--- it's the same as a

Metode array # map mengembalikan array baru

c = [1,2,3,4,5]
c.object_id #70219117705860

d = c.map {|n| n + 2}
p d #[3,4,5,6,7]
d.object_id #70284994343620  <<---- it's different than c
pengguna3007294
sumber
0

ketika Anda menggunakan map ke hash, itu secara implisit mentransmisikan hash ke sebuah array, jadi Anda memilikinya

[["d", [11, 22]], ["f", [33, 44, 55]]]

vs. setiap {...} hanya memberikan Anda kembali evaluasi terakhir, yaitu [11, 22] untuk ["d", [11, 22]] dan [33, 44, 55] untuk ["f", [ 33, 44, 55]]. Jadi sebelum bergabung terakhir, Anda harus

[[11, 22], [33, 44, 55]]
sawa
sumber
0

Anda juga bisa menggunakan mapdengan bang map!itu mengubah array sumber

Aleksandr Babushkin
sumber
Ini bukanlah jawaban atas pertanyaan. pertanyaannya adalah tentang perbedaan antara each, yang mengeksekusi blok yang diberikan dan mengembalikan array asli; dan map, yang mengembalikan larik dengan hasil mengeksekusi blok sebagai nilai
Sampson Crowley