35 Stimmen

Ist "find_all" und "select" dasselbe?

Diese beiden Aussagen geben mir die gleichen Ergebnisse:

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

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

Ist find_all nur ein Alias? Gibt es einen Grund, den einen vor dem anderen zu verwenden?

69voto

wacko Punkte 3364

#find_all und #select sind sehr ähnlich; der Unterschied ist sehr subtil. In den meisten Fällen sind sie äquivalent. Es hängt davon ab, welche Klasse es implementiert.

Enumerable#find_all und Enumerable#select laufen mit demselben Code.

Das Gleiche gilt für Array und Range, da sie die Implementierung von Enumerable verwenden.

Im Fall von Hash wird #select neu definiert, um anstelle eines Arrays ein Hash zurückzugeben, aber #find_all wird von Enumerable geerbt.

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

16voto

Arup Rakshit Punkte 113145

Enumerable#find_all Gibt ein Array zurück, das alle Elemente von enum enthält, für die der angegebene Block einen wahren Wert zurückgibt, was nicht der Fall für select ist. Enumerable#select gibt das Array zurück, falls das Empfängerobjekt, auf das Sie die Methode #select aufrufen, nicht über seine eigene #select Methode verfügt. Andernfalls gibt das Empfängerobjekt, auf das Sie die Methode #select aufrufen, einen ähnlichen Empfängertyp zurück, nachdem die Bedingung des Blocks verarbeitet wurde.

Wie Hash#select Gibt einen neuen Hash zurück, der aus Einträgen besteht, für die der Block true zurückgibt und Array#select Gibt ein neues Array zurück, das alle Elemente von ary enthält, für die der angegebene Block einen wahren Wert zurückgibt. Jetzt wird Ihnen Range#select ein Array zurückgeben, da die Klasse Range keine eigene Instanzmethode mit dem Namen #select hat. Anstatt als Enumerable zu sein, ruft es Enumerable#select auf.

rng = (1..4)
ary = [1,2]
hsh = {:a => 1}

rng.method(:select) # => #
hsh.method(:select) # => #
ary.method(:select) # => #

Hier ist eine vollständige Demonstration mit einem Beispiel zugunsten meiner obigen Erklärung :

hsh = {:a => 2, :b => 3 }
ary = [1,2,3]
rng = (1..3)

# Schau, find_all gibt immer ein Array zurück.
hsh.find_all{ true } # => [[:a, 2], [:b, 3]]
ary.find_all{ true } # => [1, 2, 3]
rng.find_all{ true } # => [1, 2, 3]

# Schau, select gibt nicht immer ein Array zurück, die Erklärung warum, ist in meiner Antwort oben geschrieben.
hsh.select{ true } # => {:a=>2, :b=>3}
ary.select{ true } # => [1, 2, 3]
rng.select{ true } # => [1, 2, 3]

8voto

Dylan Markow Punkte 120337

Ja, für Arrays liefern sie identische Ergebnisse. Bei anderen Dingen (z.B. Hashes) können sie jedoch unterschiedliche Dinge zurückgeben.

Laut der Enumerable-Dokumentation für select und find_all verweisen beide Methoden auf den gleichen Quellcode und geben entweder ein Array zurück (wenn ein Block übergeben wird) oder einen Enumerator (wenn kein Block übergeben wird).

Obwohl die Array-Klasse ihre eigene Version von select implementiert (aber Enumerable die Funktion find_all behandelt), erledigen sie dennoch dasselbe.

-1voto

find_all


mit einem Array werden die Ergebnisse als Array zurückgegeben

mit einem Hash werden die Ergebnisse als Array zurückgegeben


select

mit einem Array werden die Ergebnisse als Array zurückgegeben

mit einem Hash werden die Ergebnisse als Hash zurückgegeben


CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X