Spis treściKliknij link, aby przejść do wybranego miejsca
Ta treść została automatycznie przetłumaczona z ukraińskiego.
W Ruby konstrukcja map(&:name) jest skrótem do zastosowania metody do każdego elementu kolekcji. Ta forma jest używana, aby kod był krótszy i bardziej czytelny. Przyjrzyjmy się dokładniej, co dokładnie oznacza ten wyraz.
Metoda map jest używana do przechodzenia przez każdy element kolekcji (iteracja) i wykonywania bloku kodu dla każdego elementu. W odpowiedzi zwracany jest nowy tablica z wynikami wykonania bloku.
[1, 2, 3].map { |n| n * 2 }
# => [2, 4, 6]
Co oznacza &:name?
Ta (&:name w wyrażeniu array.map(&:name)) część jest używana do skrócenia bloku, który wywołuje metodę name dla każdego elementu. Jest to równoważne:
array.map { |item| item.name }
To znaczy:
# Oto to:
array.map { |item| item.name }
# A to:
array.map(&:name)
# Wykonuje tę samą akcję, ale druga wersja ma skróconą formę
Przykład
class User
attr_accessor :name
def initialize(name)
@name = name
end
end
users = [User.new('Alice'), User.new('Bob'), User.new('Charlie')]
names = users.map(&:name)
# => ["Alice", "Bob", "Charlie"]
# Spróbujmy 'dłuższej' wersji
names = users.map{ |user| user.name }
# => ["Alice", "Bob", "Charlie"]
Jak widzimy, obie wersje robią to samo. A co z wydajnością? Sprawdźmy benchmarki.
Benchmarki
require 'benchmark'
class User
attr_accessor :name
def initialize(name)
@name = name
end
end
# Generowanie dużej tablicy użytkowników
users = Array.new(100_000) { |i| User.new("User#{i}") }
# Benchmarking
results = Benchmark.bm do |x|
x.report('map(&:name)') do
users.map(&:name)
end
x.report('map { |user| user.name }') do
users.map { |user| user.name }
end
end
puts results
Wynik na mojej maszynie:
[#<Benchmark::Tms:0x000000010dd19ad0 @cstime=0.0, @cutime=0.0, @label="map(&:name)", @real=0.008466999977827072, @stime=0.00038199999999999346, @total=0.0077390000000007175, @utime=0.007357000000000724>,
#<Benchmark::Tms:0x000000010dd19670 @cstime=0.0, @cutime=0.0, @label="map { |user| user.name }", @real=0.008027000352740288, @stime=0.0003069999999999462, @total=0.007962000000001468, @utime=0.007655000000001522>]
Ogólnie, skrócona wersja jest bardziej zoptymalizowana i szybsza. Ale w moim przykładzie wyniki są mniej więcej takie same. Należy mieć bardziej masywny zestaw danych, aby benchmark pokazał różnicę. Dlatego domyślnie używaj skróconej (optymalizowanej wersji) wywołania metody map. Może zrobię osobny wpis z benchmarkami.
Ten post nie ma jeszcze żadnych dodatków od autora.