Эти два утверждения дают мне те же результаты:
[1,2,3,4].find_all { |x| x.even? }
[1,2,3,4].select{ |x| x.even? }
Является ли find_all просто псевдонимом? Есть ли причина использовать один над другим?
Эти два утверждения дают мне те же результаты:
[1,2,3,4].find_all { |x| x.even? }
[1,2,3,4].select{ |x| x.even? }
Является ли find_all просто псевдонимом? Есть ли причина использовать один над другим?
#find_all и #select очень похожи; разница очень тонкая. В большинстве случаев они эквивалентны. Это зависит от класса, реализующего его.
Enumerable#find_all и Enumerable#select работают по одному и тому же коду.
То же самое происходит для Array и Range, поскольку они используют реализацию Enumerable.
В случае Hash переопределяется #select, чтобы возвращать Hash вместо массива, но #find_all наследуется от Enumerable
a = [1, 2, 3, 4, 5, 6]
h = {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6}
a.select{|x| x.even?} # => [2, 4, 6]
a.find_all{|x| x.even?} # => [2, 4, 6]
h.select{|k,v| v.even?} # => {:b=>2, :d=>4, :f=>6}
h.find_all{|k,v| v.even?} # => [[:b, 2], [:d, 4], [:f, 6]]
Enumerable#find_all Возвращает массив, содержащий все элементы перечисления, для которых данный блок возвращает истинное значение, что не относится к select. Enumerable#select возвращает Array, если получатель, на который вы вызываете метод #select, не имеет собственного метода #select. В противном случае, на каком приемнике вы вызываете метод #select, он будет возвращать аналогичный тип получателя после обработки состояния блока.
Как Hash#select Возвращает новый хеш, состоящий из записей, для которых блок возвращает true и Array#select Возвращает новый массив, содержащий все элементы ary, для которых данный блок возвращает истинное значение. Теперь Range#select вернет обратно Array, поскольку класс Range не имеет собственного метода экземпляра, называемого #select. Вместо Enumerable он вызывается Enumerable#select.
rng = (1..4)
ary = [1,2]
hsh = {:a => 1}
rng.method(:select) # => #<Method: Range(Enumerable)#select>
hsh.method(:select) # => #<Method: Hash#select>
ary.method(:select) # => #<Method: Array#select>
Вот полная демонстрация с примером в пользу моего объяснения выше:
hsh = {:a => 2, :b => 3 }
ary = [1,2,3]
rng = (1..3)
# Look find_all always gives Array.
hsh.find_all{ true } # => [[:a, 2], [:b, 3]]
ary.find_all{ true } # => [1, 2, 3]
rng.find_all{ true } # => [1, 2, 3]
# Look select not giving Array always, explanation of why so is written
# above in my answer.
hsh.select{ true } # => {:a=>2, :b=>3}
ary.select{ true } # => [1, 2, 3]
rng.select{ true } # => [1, 2, 3]
Да, для массивов они возвращают одинаковые результаты. Для других вещей (например, хэши) они могут возвращать разные вещи.
В соответствии с документацией Enumerable для select и find_all оба метода указывают на тот же исходный код, и оба возвращают либо массив (если задан блок), либо Enumerator (если не задан блок).
В то время как класс Array реализует собственную версию select (но позволяет Enumerable handle find_all), они все равно выполняют одно и то же.