Рубиновый Хэш-Фильтр Белого Списка
Я пытаюсь выяснить, как я могу отфильтровать пары ключ / значение из одного фильтра в другой
например я хочу взять этот хэш
x = { "one" => "one", "two" => "two", "three" => "three"}
y = x.some_function
y == { "one" => "one", "two" => "two"}
Спасибо за помощь
EDIT: вероятно, следует упомянуть, что в этом примере я хочу, чтобы он вел себя как фильтр белого списка. То есть я знаю, чего хочу, а не чего не хочу.
7 ответов:
может быть, это то, что вы хотите.
wanted_keys = %w[one two] x = { "one" => "one", "two" => "two", "three" => "three"} x.select { |key,_| wanted_keys.include? key }
перечисляемый mixin, который включен, например, в массив и хэш, предоставляет множество полезных методов, таких как select/reject/each/etc.. Я предлагаю вам взглянуть на документацию для него с помощью Ri Enumerable.
библиотека ActiveSupport Rails также дает вам срез и за исключением работы с хэшем на ключевом уровне:
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" }
Это довольно мило, и я использую их все время.
вы можете просто использовать встроенную хэш-функцию reject.
x = { "one" => "one", "two" => "two", "three" => "three"} y = x.reject {|key,value| key == "three" } y == { "one" => "one", "two" => "two"}
вы можете поместить любую логику, которую вы хотите в отклонение,и если блок возвращает true, он пропустит этот ключ, значение в новом хэше.
улучшение немного @scottd ответ, если вы используете rails и есть список того, что вам нужно, вы можете расширить список в качестве параметров из среза. Например
hash = { "one" => "one", "two" => "two", "three" => "three"} keys_whitelist = %W(one two) hash.slice(*keys_whitelist)
и без rails, для любой версии ruby, вы можете сделать следующее:
hash = { "one" => "one", "two" => "two", "three" => "three"} keys_whitelist = %W(one two) Hash[hash.find_all{|k,v| keys_whitelist.include?(k)}]
используя комбинацию ответов каждого, я придумал это решение:
wanted_keys = %w[one two] x = { "one" => "one", "two" => "two", "three" => "three"} x.reject { |key,_| !wanted_keys.include? key } =>{ "one" => "one", "two" => "two"}
Спасибо за помощь ребята!
EDIT:
выше работает в 1.8.7+
следующие работы в 1.9+ :
x. выберите {/key,_ / wanted_keys.включить? ключ }
Я бы использовал лямбда для фильтрации. Это позволит вам написать сложную логику фильтрации и упростить ее тестирование. Тот факт, что логика фильтрации извлечена, позволит повторно использовать ее в других контекстах.
ex:
x = { "one" => "one", "two" => "two", "three" => "three"} matcher = ->(key,value) { # FILTERING LOGIC HERE !key[/three/] } x.select(&matcher) == { "one" => "one", "two" => "two"}