web-dev-qa-db-fra.com

Filtre de liste blanche de hachage Ruby

J'essaie de comprendre comment filtrer les paires de clés et de valeurs d'un filtre à un autre

Par exemple je veux prendre ce hash

x = { "one" => "one", "two" => "two", "three" => "three"}

y = x.some_function

y == { "one" => "one", "two" => "two"}

Merci de votre aide

EDIT: devrait probablement mentionner que dans cet exemple, je veux qu'il se comporte comme un filtre de liste blanche. C'est-à-dire que je sais ce que je veux, pas ce que je ne veux pas.

63
stellard

Peut-être que c'est ce que vous voulez.

wanted_keys = %w[one two]
x = { "one" => "one", "two" => "two", "three" => "three"}
x.select { |key,_| wanted_keys.include? key }

Le mixin Enumerable qui est inclus dans, par exemple, Array and Hash fournit de nombreuses méthodes utiles, telles que sélectionner/rejeter/chaque/etc .. Je vous suggère de consulter la documentation correspondante avec ri Enumerable.

51
sris

La bibliothèque ActiveSupport de Rails vous donne également des tranches et à l'exception du traitement du hachage au niveau clé

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

Ce sont assez Nice, et je les utilise tout le temps.

100
Brian Guthrie

Vous pouvez simplement utiliser la fonction de rejet intégrée de Hash.

x = { "one" => "one", "two" => "two", "three" => "three"}
y = x.reject {|key,value| key == "three" }
y == { "one" => "one", "two" => "two"}

Vous pouvez mettre la logique de votre choix dans le rejet et si le bloc renvoie true, il ignorera cette clé, valeur dans le nouveau hachage.

48
scottd

Pour améliorer un peu la réponse @scottd, si vous utilisez Rails et avez une liste de ce dont vous avez besoin, vous pouvez développer la liste en tant que paramètres de la tranche. Par exemple

hash = { "one" => "one", "two" => "two", "three" => "three"}
keys_whitelist = %W(one two)
hash.slice(*keys_whitelist)

Et sans Rails, quelle que soit la version de Ruby, vous pouvez effectuer les opérations suivantes:

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

En combinant les réponses de chacun, je propose cette solution:

 wanted_keys = %w[one two]
 x = { "one" => "one", "two" => "two", "three" => "three"}
 x.reject { |key,_| !wanted_keys.include? key }
 =>{ "one" => "one", "two" => "two"}

Merci pour votre aide les gars!

MODIFIER: 

Ce qui précède fonctionne en 1.8.7+ 

Ce qui suit fonctionne dans 1.9+:

x.select {| key, _ | wanted_keys.include? clé}

6
stellard

J'utiliserais un lambda pour filtrer. Cela vous permettra à la fois d’écrire une logique de filtrage complexe et de la tester facilement. Le fait que la logique de filtrage soit extraite permettra de la réutiliser dans d’autres contextes. 

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