webentwicklung-frage-antwort-db.com.de

Ruby Hash Whitelist Filter

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.

63
stellard

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.

51
sris

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.

100
Brian Guthrie

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.

48
scottd

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)}] 
7
fotanus
y = x.reject {|k,v| k == "three"}
7
Brian Campbell

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 }

6
stellard

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"}
0
metakungfu