Фильтр белого белья Ruby Hash
Я пытаюсь выяснить, как я могу отфильтровать пары ключей и значений из одного фильтра в другой
Например, я хочу использовать этот хеш
x = { "one" => "one", "two" => "two", "three" => "three"}
y = x.some_function
y == { "one" => "one", "two" => "two"}
Спасибо за помощь
EDIT: возможно, следует упомянуть, что в этом примере я хочу, чтобы он вел себя как белый список. То есть я знаю, чего хочу, а не то, чего я не хочу.
Ответы
Ответ 1
Возможно, это то, что вы хотите.
wanted_keys = %w[one two]
x = { "one" => "one", "two" => "two", "three" => "three"}
x.select { |key,_| wanted_keys.include? key }
Перечислимый миксин, который включен в, например, Array и Hash предоставляют множество полезных методов, таких как select/reject/each/etc. Я предлагаю вам ознакомиться с документацией для него с ri Enumerable.
Ответ 2
Библиотека 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" }
Это довольно приятно, и я использую их все время.
Ответ 3
Вы можете просто использовать встроенную функцию Hash.
x = { "one" => "one", "two" => "two", "three" => "three"}
y = x.reject {|key,value| key == "three" }
y == { "one" => "one", "two" => "two"}
Вы можете поместить любую логику в отклонение, и если блок вернет true, он пропустит этот ключ, значение в новом хеше.
Ответ 4
y = x.reject {|k,v| k == "three"}
Ответ 5
Используя комбинацию всех ответов, я придумал это решение:
wanted_keys = %w[one two]
x = { "one" => "one", "two" => "two", "three" => "three"}
x.reject { |key,_| !wanted_keys.include? key }
=>{ "one" => "one", "two" => "two"}
Спасибо за помощь, ребята!
ИЗМЕНИТЬ:
Вышеизложенное работает в 1.8.7+
В версии 1.9+ работает следующее:
x.select {| key, _ | wanted_keys.include? ключ}
Ответ 6
Улучшение ответа на бит @scottd, если вы используете рельсы и имеете список того, что вам нужно, вы можете развернуть список как параметры из среза. Например
hash = { "one" => "one", "two" => "two", "three" => "three"}
keys_whitelist = %W(one two)
hash.slice(*keys_whitelist)
И без рельсов для любой рубиновой версии вы можете сделать следующее:
hash = { "one" => "one", "two" => "two", "three" => "three"}
keys_whitelist = %W(one two)
Hash[hash.find_all{|k,v| keys_whitelist.include?(k)}]
Ответ 7
Я бы использовал лямбда для фильтрации. Это позволит вам написать сложную логику фильтрации и упростить ее проверку. Тот факт, что логика фильтрации извлечена, позволит повторно использовать ее в других контекстах.
ex:
x = { "one" => "one", "two" => "two", "three" => "three"}
matcher = ->(key,value) {
# FILTERING LOGIC HERE
!key[/three/]
}
x.select(&matcher) == { "one" => "one", "two" => "two"}