Ich habe ein Array, über das ich iterieren und einige der Elemente löschen möchte. Das funktioniert nicht:
a = [1, 2, 3, 4, 5]
a.each do |x|
next if x < 3
a.delete x
# do something with x
end
a #=> [1, 2, 4]
Ich möchte a
sein [1, 2]
. Wie kann ich das umgehen?
Antworten:
a.delete_if { |x| x >= 3 }
Siehe Methodendokumentation hier
Aktualisieren:
Sie können mit x im Block umgehen:
a.delete_if do |element| if element >= 3 do_something_with(element) true # Make sure the if statement returns true, so it gets marked for deletion end end
quelle
x
wenn es gelöscht wird. Soll ich das in den Block legen?reject!
.reject!
wird,nil
wenn keine Elemente abgelehnt wurden, währenddelete_if
das ursprüngliche Array zurückgegeben wird.Sie müssen nicht aus dem Array löschen, sondern können es filtern:
a = [1, 2, 3, 4, 5] b = a.select {|x| x < 3} puts b.inspect # => [1,2] b.each {|i| puts i} # do something to each here
quelle
.select
gibt ein neues Ruby-Objekt zurück, das mehr Speicher benötigt. Sehen Sie dieses Beispiel pastebin.com/23e10bKyIch habe diese Frage vor nicht allzu langer Zeit gestellt.
Löschen beim Iterieren in Ruby?
Es funktioniert nicht, weil Ruby die
.each
Schleife verlässt , wenn er versucht, etwas zu löschen. Wenn Sie einfach Dinge aus dem Array löschen möchten,delete_if
funktioniert dies, aber wenn Sie mehr Kontrolle wünschen, funktioniert die Lösung, die ich in diesem Thread habe, obwohl sie irgendwie hässlich ist.quelle
each
iteriert effektiv mithilfe des Index. Wenn Sie also löschen, sind die Indizes unterschiedlich, und bei der nächsten Iteration werden die neuen Indizes verwendet. Versuchen Sie Folgendes :arr = [1,2,3,4,5,6]; arr.each_with_index {|e,i| p [arr, e, i]; next if e < 3; arr.delete e }
. Wenn Element 3 erreicht ist, ist der Index 2. Nachdem 3 gelöscht wurde, erhöht die nächste Iteration den Index auf 3 und das Element ist 5. Daher wird 4 übersprungen. 6 wird aus dem gleichen Grund übersprungen.Eine andere Möglichkeit ist die Verwendung von
reject!
, was wohl klarer ist, da es eine hat,!
was bedeutet, dass "dies das Array ändert". Der einzige Unterschied besteht darin, dass zurückgegebenreject!
wird,nil
wenn keine Änderungen vorgenommen wurden.a.delete_if {|x| x >= 3 }
oder
a.reject! {|x| x >= 3 }
wird beides gut funktionieren.
quelle