Ruby Hash Whitelist Filter - PullRequest
       28

Ruby Hash Whitelist Filter

64 голосов
/ 03 апреля 2009

Я пытаюсь выяснить, как я могу отфильтровать пары ключей и значений из одного фильтра в другой

Например, я хочу взять этот хэш

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

y = x.some_function

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

Спасибо за вашу помощь

РЕДАКТИРОВАТЬ: вероятно, следует упомянуть, что в этом примере я хочу, чтобы он вел себя как фильтр белого списка. То есть я знаю, что хочу, а не то, чего не хочу.

Ответы [ 7 ]

102 голосов
/ 04 апреля 2009

Библиотека 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" }

Это довольно мило, и я использую их все время.

53 голосов
/ 03 апреля 2009

Может быть, это то, что вы хотите.

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.

49 голосов
/ 03 апреля 2009

Вы можете просто использовать встроенную функцию отклонения хэша.

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

Вы можете поместить любую отклоняющуюся логику в отклонение, и если блок вернет true, он пропустит этот ключ, значение в новом хеше.

8 голосов
/ 18 июля 2013

Улучшение ответа @scottd. Если вы используете рельсы и у вас есть список того, что вам нужно, вы можете расширить список как параметры из слайса. Например

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

И без направляющих, для любой версии ruby ​​вы можете сделать следующее:

hash = { "one" => "one", "two" => "two", "three" => "three"}
keys_whitelist = %W(one two)
Hash[hash.find_all{|k,v| keys_whitelist.include?(k)}] 
7 голосов
/ 03 апреля 2009

Используя комбинацию ответов каждого, я нашел решение:

 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? ключ}

7 голосов
/ 03 апреля 2009
y = x.reject {|k,v| k == "three"}
0 голосов
/ 04 июля 2017

Я бы использовал лямбду для фильтрации. Это позволит вам написать сложную логику фильтрации и упростить ее тестирование. Тот факт, что логика фильтрации извлечена, позволит использовать ее в других контекстах.

например:

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

matcher = ->(key,value) { 
  # FILTERING LOGIC HERE 
   !key[/three/]
}

x.select(&matcher) == { "one" => "one", "two" => "two"}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...