Ruby Hash Whitelist Filter

RubyHashmap

Ruby Problem Overview


I am trying to figure out how I can filter out key and value pairs from one filter into another

For example I want to take this hash

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

y = x.some_function

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

Thanks for your help

EDIT: should probably mention that in this example, I want it to behave as a whitelist filter. That is, I know what I want, not what I don't want.

Ruby Solutions


Solution 1 - Ruby

Rails' ActiveSupport library also gives you slice and except for dealing with the hash on a key level:

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

These are quite nice, and I use them all the time.

Solution 2 - Ruby

Maybe this it what you want.

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

The Enumerable mixin which is included in e.g. Array and Hash provides a lot of useful methods like select/reject/each/etc.. I suggest that you take a look at the documentation for it with ri Enumerable.

Solution 3 - Ruby

You can just use the built in Hash function reject.

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

You can put whatever logic you want into the reject, and if the block returns true it will skip that key,value in the new hash.

Solution 4 - Ruby

Improving a bit @scottd answer, if you are using rails and have a list of what you need, you can expand the list as parameters from slice. For example

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

And without rails, for any ruby version, you can do the following:

hash = { "one" => "one", "two" => "two", "three" => "three"}
keys_whitelist = %W(one two)
Hash[hash.find_all{|k,v| keys_whitelist.include?(k)}] 

Solution 5 - Ruby

y = x.reject {|k,v| k == "three"}

Solution 6 - Ruby

Using a combination of everyone's answers I have come up with this solution:

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

Thanks for your help guys!

EDIT:

The above works in 1.8.7+

The following works in 1.9+ :

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

Solution 7 - Ruby

I'd use a lambda to filter. This will both allow you to write complex filtering logic & make it easy to test it. The fact that the filtering logic is extracted will allow to reuse it in other contexts.

ex:

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

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

x.select(&matcher) == { "one" => "one", "two" => "two"}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionstellardView Question on Stackoverflow
Solution 1 - RubyBrian GuthrieView Answer on Stackoverflow
Solution 2 - RubysrisView Answer on Stackoverflow
Solution 3 - RubyscottdView Answer on Stackoverflow
Solution 4 - RubyfotanusView Answer on Stackoverflow
Solution 5 - RubyBrian CampbellView Answer on Stackoverflow
Solution 6 - RubystellardView Answer on Stackoverflow
Solution 7 - RubymetakungfuView Answer on Stackoverflow