Ich versuche herauszufinden, wie ich Schlüssel- und Wertepaare aus einem Filter in einen anderen filtern kann
Zum Beispiel möchte ich diesen Hash nehmen
x = { "one" => "one", "two" => "two", "three" => "three"}
y = x.some_function
y == { "one" => "one", "two" => "two"}
Danke für Ihre Hilfe
EDIT: sollte wahrscheinlich erwähnen, dass ich in diesem Beispiel als Whitelist-Filter fungieren möchte. Das heißt, ich weiß, was ich will, nicht was ich nicht will.
Vielleicht ist es das was du willst.
wanted_keys = %w[one two]
x = { "one" => "one", "two" => "two", "three" => "three"}
x.select { |key,_| wanted_keys.include? key }
Das Enumerable-Mixin, das z. Array and Hash bietet viele nützliche Methoden wie select/reject/each/etc .. Ich schlage vor, dass Sie sich die Dokumentation dazu mit ri Enumerable ansehen.
Die ActiveSupport-Bibliothek von Rails bietet Ihnen auch Slice und abgesehen von der Behandlung des Hash auf einer Schlüsselebene
y = x.slice("one", "two") # => { "one" => "one", "two" => "two" }
y = x.except("three") # => { "one" => "one", "two" => "two" }
x.slice!("one", "two") # x is now { "one" => "one", "two" => "two" }
Das ist ganz nett und ich benutze sie die ganze Zeit.
Sie können einfach die eingebaute Hash-Funktion ablehnen.
x = { "one" => "one", "two" => "two", "three" => "three"}
y = x.reject {|key,value| key == "three" }
y == { "one" => "one", "two" => "two"}
Sie können jede gewünschte Logik in den Ablehnungsbefehl einfügen. Wenn der Block den Wert true zurückgibt, wird dieser Schlüssel übersprungen, der Wert im neuen Hash.
Verbessern Sie die Antwort ein wenig @ scottd. Wenn Sie Rails verwenden und eine Liste mit den benötigten Informationen haben, können Sie die Liste als Parameter von slice erweitern. Zum Beispiel
hash = { "one" => "one", "two" => "two", "three" => "three"}
keys_whitelist = %W(one two)
hash.slice(*keys_whitelist)
Und ohne Rails können Sie für jede Ruby-Version Folgendes tun:
hash = { "one" => "one", "two" => "two", "three" => "three"}
keys_whitelist = %W(one two)
Hash[hash.find_all{|k,v| keys_whitelist.include?(k)}]
y = x.reject {|k,v| k == "three"}
Mit einer Kombination aller Antworten habe ich diese Lösung gefunden:
wanted_keys = %w[one two]
x = { "one" => "one", "two" => "two", "three" => "three"}
x.reject { |key,_| !wanted_keys.include? key }
=>{ "one" => "one", "two" => "two"}
Danke für Ihre Hilfe, Jungs!
BEARBEITEN:
Das Obige funktioniert in 1.8.7+
Folgendes funktioniert in 1.9+:
x.select {| key, _ | wanted_keys.include? Schlüssel }
Ich würde ein Lambda verwenden, um zu filtern. Dadurch können Sie sowohl komplexe Filterlogik schreiben als auch es einfach testen. Die Tatsache, dass die Filterlogik extrahiert wird, ermöglicht die Wiederverwendung in anderen Zusammenhängen.
ex:
x = { "one" => "one", "two" => "two", "three" => "three"}
matcher = ->(key,value) {
# FILTERING LOGIC HERE
!key[/three/]
}
x.select(&matcher) == { "one" => "one", "two" => "two"}