Подтвердить что ты не робот

Является ли "find_all" и "выбирает" то же самое?

Эти два утверждения дают мне те же результаты:

[1,2,3,4].find_all { |x| x.even? }

[1,2,3,4].select{ |x| x.even? }

Является ли find_all просто псевдонимом? Есть ли причина использовать один над другим?

4b9b3361

Ответ 1

#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]]

Ответ 2

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]

Ответ 3

Да, для массивов они возвращают одинаковые результаты. Для других вещей (например, хэши) они могут возвращать разные вещи.

В соответствии с документацией Enumerable для select и find_all оба метода указывают на тот же исходный код, и оба возвращают либо массив (если задан блок), либо Enumerator (если не задан блок).

В то время как класс Array реализует собственную версию select (но позволяет Enumerable handle find_all), они все равно выполняют одно и то же.