Ruby-Arrays: select (), collect () und map ()

106

Die Syntax für das Mapping:

a = ["a", "b", "c", "d"]      #=> ["a", "b", "c", "d"] 
a.map {|item|"a" == item}     #=> [true, false, false, false] 
a.select {|item|"a" == item}  #=> ["a"]

Frage, wie wäre es, wenn ich habe:

 irb(main):105:0> details[1]
 => {:sku=>"507772-B21", :desc=>"HP 1TB 3G SATA 7.2K RPM LFF (3 .", :qty=>"", 
 :qty2=>"1", :price=>"5,204.34 P"}

Ich möchte jeden Eintrag löschen, der einen leeren Mengenwert in diesem Array hat, oder nur diejenigen auswählen, die einen Wert enthalten.

Ich habe es versucht:

details.map {|item|"" == item}

Gibt einfach eine Menge false zurück und wenn ich dieselbe verwende, ändere ich einfach die Karte, um Folgendes auszuwählen:

[]
ingalcala
quelle
Wenn Sie genau hinschauen, sieht es so aus, als wäre es eine Reihe von Hashes
Emily
@ Emily: Sehr wahr, das habe ich gerade gemerkt. Das letzte Codebeispiel hat mich anders denken lassen, weil :qtyes dort nicht einmal erscheint.
Niklas B.

Antworten:

131

Es sieht aus wie detailseine Reihe von Hashes. Also iteminnerhalb des Blocks wird die ganze Hash sein. Um den :qtySchlüssel zu überprüfen , gehen Sie wie folgt vor:

details.select{ |item| item[:qty] != "" }

Dadurch erhalten Sie alle Elemente, bei denen der :qtySchlüssel keine leere Zeichenfolge ist.

offizielle ausgewählte Dokumentation

Emily
quelle
26

EDIT: Ich habe gerade festgestellt, dass Sie filtern möchten details, was eine Reihe von Hashes ist. In diesem Fall könnten Sie tun

details.reject { |item| item[:qty].empty? }

Die innere Datenstruktur selbst ist kein Array, sondern ein Hash. Sie können auch selecthier verwenden, aber der Block erhält in diesem Fall den Schlüssel und den Wert:

irb(main):001:0> h = {:sku=>"507772-B21", :desc=>"HP 1TB 3G SATA 7.2K RPM LFF (3 .", :qty=>"", :qty2=>"1", :price=>"5,204.34 P"}
irb(main):002:0> h.select { |key, value| !value.empty? }
=> {:sku=>"507772-B21", :desc=>"HP 1TB 3G SATA 7.2K RPM LFF (3 .", 
    :qty2=>"1", :price=>"5,204.34 P"}

Oder using reject, was umgekehrt ist select(schließt alle Elemente aus, für die die angegebene Bedingung gilt):

h.reject { |key, value| value.empty? }

Beachten Sie, dass dies Ruby 1.9 ist. Wenn Sie die Kompatibilität mit 1.8 beibehalten müssen, können Sie Folgendes tun:

Hash[h.reject { |key, value| value.empty? }]
Niklas B.
quelle
@ingalcala: Ich habe gerade festgestellt, dass meine Antwort nicht das ist, was du brauchst. Bitte überprüfen Sie meine Bearbeitung, um herauszufinden, wie das detailsArray selbst gefiltert werden kann.
Niklas B.
9

{}Verwenden Sie beim Umgang mit einem Hash sowohl den Schlüssel als auch den Wert für den Block innerhalb des ||.

details.map {|key,item|"" == item}

=>[false, false, true, false, false]
Michael Berkowski
quelle