Ruby hash keys to array conditional on hash value - ruby

I would like to extract hash key values to an array when a condition is met. For example, with hash h I want to extract the keys where the values are "true":
h = { :a => true, :b => false, :c =>true }
I've come up with this:
h.map {|k,v| k if v==true} - [nil]
Any alternatives?

h.select { |_, v| v }.keys
Will do the same, but in more readable way.

You can also do
s = {}
h.each do |k,v|
s[k] = v if v==true
end

Related

Best way to convert hash keys to array only if their values are set to true

I'm trying to find an elegant and compact way to convert hash keys into array that contains only those that have true as value
example = {"foo" => true, "bar" => false, "baz" => true}
become
example = ["foo", "baz"]
example = example.keys.select {|key| example[key].eql? true}
p example
output
["foo", "baz"]
The shortest would be example.select{|k, v| v}
to extract the keys simply add .keys
EDIT: if like Cary suggests there would be other than boolean values you would have to check for v == true or v.eql? true
My 2 cents:
example.collect{|k, v| k if v}.compact
output: ["foo", "baz"]
Which can work also picking false:
example.collect{|k, v| k if !v}.compact
output: ["bar"]
..or
There are a lot of different ways to do this. Here's another one:
example.reduce([]) { |memo, (k, v)| v ? memo << k : memo }
Or, similarly:
example.each_with_object([]) { |(k, v), memo| memo << k if v }
Or you can use my nutty piecewise gem:
example.piecewise { |yielder, (k, v)| yielder << k if v }

Print keys for certain value

I have a hash that looks similar to:
hash = {key1: true, key2: false, key3: false, key4: true}
and I would like to iterate through the hash and print each key which has a true value. The result should look like:
key1
key4
How am I going to do that? I tried:
hash.each do |k,v|
puts k if true
end
While iterating is fine, the goal might be achieved in more rubyish manner:
hash.select { |_, v| v }.keys
or, if equality to true (as an opposite to being just truthy) is significant:
hash.select { |_, v| v == true }.keys
To print the result out:
puts hash.select { |_, v| v == true }.keys
Further information on how Hash#select works.
To print all the keys matched as “key1 and key4”:
puts hash.select { |_, v| v == true }.keys.join(' and ')
hash.each do |k, v|
puts k if v == true
end
You can use map and compact methods:
hash.map { |k, v| k if v }.compact
It is as simple as:
hash.each do |k,v|
puts k if v
end

Create array of individual hashes from one hash

Given a hash of key/value pairs, how can I turn that into an array of individual hashes for each key/value pair.
So for example, starting with:
{"hello"=>"bonjour", "goodbye"=>"au revoir"}
And turning that into:
[ {"hello" => "bonjour"}, {"goodbye" => "au revoir"} ]
I got that with the following but am wondering if there's an easier approach:
array = []
hash.each do |k,v|
h = Hash.new
h[k] = v
array << h
end
Do as below using Enumerable#map:
h = {"hello"=>"bonjour", "goodbye"=>"au revoir"}
h.map { |k,v| { k => v } }
# => [{"hello"=>"bonjour"}, {"goodbye"=>"au revoir"}]

Ruby - find the key(s) of the largest value(s) of a hash

I have a hash and I want to return the key(s) (or key/value pair(s)) of the max value(s) of the hash. So, if there is only one true max, it will return that one key; however, if there are multiple key/value pairs with the same value, it will return all of these keys. How can I accomplish this in Ruby?
my_hash.max_by {|k,v| v} #only returns one key/value pair
If you want all pairs, I would do something like
max = my_hash.values.max
Hash[my_hash.select { |k, v| v == max}]
A single liner:
my_hash.reduce({}){|h,(k,v)| (h[v] ||= []) << k;h}.max
irb
> z = {:tree => 3, :two => 2, 'three' => 3}
> z.reduce({}){|h,(k,v)| (h[v] ||= []) << k;h}.max
[3, [:tree, "three"]]

Ruby 1.8: Hash#sort not return hash but array (better way to do this?)

In some scenario of Ruby 1.8. If I have a hash
# k is name, v is order
foo = { "Jim" => 1, "bar" => 1, "joe" => 2}
sorted_by_values = foo.sort {|a, b| a[1] <==> b[1]}
#sorted_by_values is an array of array, it's no longer a hash!
sorted_by_values.keys.join ','
my workaround is to make method to_hash for Array class.
class Array
def to_hash(&block)
Hash[*self.collect { |k, v|
[k, v]
}.flatten]
end
end
I can then do the following:
sorted_by_values.to_hash.keys.join ','
Is there a better way to do this?
Hashes are unordered by definition. There can be no such thing as a sorted Hash. Your best bet is probably to extract the keys from the sorted array using collect and then do a join on the result
sortedByValues = foo.sort {|a, b| a[1] <==> b[1]}
sortedByValues.collect { |a| a[0] }.join ','

Resources