Create a combination of a array of hash - ruby

I have an array like:
hasharray=[{"a" => "b" } , {"c" => "d"} , {"e" => "f"}]
I want to create all combinations of this array hash of length min to max.
For instance, with min=0 and max=2, the code should return:
resultarray=[
{},
{"a" => "b" },
{"c" => "d"},
{"e" => "f"},
{"a" => "b" } , {"c" => "d"},
{"c" => "d"} , {"e" => "f"},
{"a" => "b" },{"e" => "f"}
]
How do I do it?

min = 0
max = 2
min.upto(max).flat_map {|n| hasharray.combination(n).to_a }
# => [
# [],
# [{"a"=>"b"}], [{"c"=>"d"}], [{"e"=>"f"}],
# [{"a"=>"b"}, {"c"=>"d"}], [{"a"=>"b"}, {"e"=>"f"}], [{"c"=>"d"}, {"e"=>"f"}]
# ]

Related

How to sort Ruby Hash with dynamic keys

I want to understand how I can sort ruby hashes with key and or their subkeys if need be. For examples:
Example of hash with sub_hashs
two_hash = {
'a' => {'displayName' => "A", 'name' => "Apple", 'Association' => {'id' => '1', 'type' => 'B2'}},
'c' => {'displayName' => "D", 'name' => "Banana", 'Association' => {'id' => '1', 'type' => 'B3'}},
'b' => {'displayName' => "C", 'name' => "Orange", 'Association' => {'id' => '1', 'type' => 'B1'}},
'd' => {'displayName' => "B", 'name' => "Kiwi", 'Association' => {'id' => '1', 'type' => 'B4'}}
}
Currently I can sort it like this, calling and specify the key/subkey to sort by.
puts (two_hash.sort_by {|h, k| k['displayName']})
puts (two_hash.sort_by {|h, k| k['Association']['type']})
I want to convert it to a proc and used it whenever I want given a subkey input.
I want it so I can just pass in a key or a subkey and it will sort for me. like so, is there a way to do this in Ruby?
sort_stuff_method(two_hash, ['displayname'])
sort_stuff_method(two_hash, ['Association']['type'])
This is one way to do that:
def sort_em(h, *nested_keys)
h.sort_by { |k,v| nested_keys.reduce(v) { |g,k| g[k] } }
end
sort_em(two_hash, 'displayName')
#=> [["a", {"displayName"=>"A", "name"=>"Apple",
# "Association"=>{"id"=>"1", "type"=>"B2"}}],
# ["d", {"displayName"=>"B", "name"=>"Kiwi",
# "Association"=>{"id"=>"1", "type"=>"B4"}}],
# ["b", {"displayName"=>"C", "name"=>"Orange",
# "Association"=>{"id"=>"1", "type"=>"B1"}}],
# ["c", {"displayName"=>"D", "name"=>"Banana",
# "Association"=>{"id"=>"1", "type"=>"B3"}}]]
sort_em(two_hash, 'Association', 'type')
#=> [["b", {"displayName"=>"C", "name"=>"Orange",
# "Association"=>{"id"=>"1", "type"=>"B1"}}],
# ["a", {"displayName"=>"A", "name"=>"Apple",
# "Association"=>{"id"=>"1", "type"=>"B2"}}],
# ["c", {"displayName"=>"D", "name"=>"Banana",
# "Association"=>{"id"=>"1", "type"=>"B3"}}],
# ["d", {"displayName"=>"B", "name"=>"Kiwi",
# "Association"=>{"id"=>"1", "type"=>"B4"}}]]
This of course works for any number of nested keys.
Is this what you are looking for,
def sort_stuff_method(input_hash, sort_key, sort_sub_key=nil)
input_hash.sort_by{|h,k| sort_sub_key.nil? ? k[sort_key] : k[sort_key][sort_sub_key]}
end
and you can use it like this,
sort_stuff_method(input_hash, 'displayName')
sort_stuff_method(input_hash, 'Association', 'Type')

Compare two arrays of hashes and return new object

I have two arrays of hashes.
burgers = [
{:id => 1, :name => "cheese burger"},
{:id => 2, :name => "royale"},
{:id => 3, :name => "big mac"},
{:id => 4, :name => "angus beef"}
]
eaten = [
{:burger_id => 1},
{:burger_id => 2}
]
I would like to return an array or uneaten burgers, where burgers[:id] does not equal eaten[:burger_id]. In burgers_not_eaten_method, I have the expected return value.
def burgers_not_eaten
#Not sure how to compare burger[:id] with eaten[:burger_id]
burgers.reject { |burger| burger[:id] == #eaten burger_id }
# Expected: [{:id => 3, :name => "big mac"},{:id => 4, :name => "angus beef"}]
end
You're close, to make it easy I'd snag all the "eaten" ids into an array, and check for inclusion in that array, like so:
BURGERS = [
{:id => 1, :name => "cheese burger"},
{:id => 2, :name => "royale"},
{:id => 3, :name => "big mac"},
{:id => 4, :name => "angus beef"}
]
EATEN = [
{:burger_id => 1},
{:burger_id => 2}
]
def burgers_not_eaten
eaten_ids = EATEN.map { |e| e[:burger_id] }
BURGERS.reject { |burger| eaten_ids.include?(burger[:id]) }
end
burgers_not_eaten
# => [{:id=>3, :name=>"big mac"}, {:id=>4, :name=>"angus beef"}]

How to sort lines of a hash in descending order according to one of the key-value pairs in Ruby?

I have the following hash:
lines[0] = {"a" => dog, "b" => 32, "c" =>555, "d" => 100}
lines[1] = {"a" => cat, "b" => 34, "c" =>554, "d" => 4542}
lines[2] = {"a" => bird, "b" => 31, "c" =>532435, "d" => 23}
I would like to sort the hash by "b" in descending order so that I end up with:
lines[0] = {"a" => cat, "b" => 34, "c" =>554, "d" => 4542}
lines[1] = {"a" => dog, "b" => 32, "c" =>555, "d" => 100}
lines[2] = {"a" => bird, "b" => 31, "c" =>532435, "d" => 23}
What would be the best way to achieve that? Is there a method in Ruby that does this for you?
You seem to have a peculiar case where lines is NOT an array but a Hash, so you want to reassign values for each key based on value's order, for that first create array out of Hash, sort that, and that create a Hash based on new index e.g.
lines = {}
lines[0] = {"a" => :dog, "b" => 32, "c" =>555, "d" => 100}
lines[1] = {"a" => :cat, "b" => 34, "c" =>554, "d" => 4542}
lines[2] = {"a" => :bird, "b" => 31, "c" =>532435, "d" => 23}
require 'pp'
pp Hash[lines.map.sort_by {|k,v| -v["b"]}.map.with_index {|v, index| [index, v[1]]}]
output is:
{0=>{"a"=>:cat, "b"=>34, "c"=>554, "d"=>4542},
1=>{"a"=>:dog, "b"=>32, "c"=>555, "d"=>100},
2=>{"a"=>:bird, "b"=>31, "c"=>532435, "d"=>23}}
That said, why lines is a Hash? it could better be represented by an Array
lines.sort_by! {|hash| -hash["b"]}
You can do
lines.sort! { |a, b| b["b"] <=> a["b"] }

Ruby 1.9 - Convert hash based off regex

Need to convert {"P1" => "ABC", "R1" => "15", "P2" => "LOP", "R2" => "22"}
The hash keys could be in any order.
For instance they could also be {"P1" => "ABC", "R2" => "22", "R1" => "15", "P2" => "LOP"}
or {"R1" => "15", "R2" => "22", "P1" => "ABC", "P2" => "LOP"}
Into this {"ABC" => "15", "LOP" => "22"}
The matcher between keys is the digit.
I'm looking for {P1.value => R1.value, P2.value => R2.value}
P indicating key and R indicating value
The way I'm currently doing it is looping over the initial hash and creating a hash like {1 => 'ABC', 2 => 'LOP'} and also creating {1 => "15", 2 => "22"}.
I then loop over the first new hash and use the key to match the second hash and create the final hash. {"ABC" => "15", "LOP" => "22"}
I'm sure there is a more elegant solution but I just can't think of it.
Check Kernel#Hash. This works for any number of Pn/Rn:
h = {"P1" => "ABC", "R2" => "22", "R1" => "15", "P2" => "LOP"}
Hash[*h.sort_by { |k, v| [k[1..-1].to_i, k[0]] }.map { |k, v| v }]
#=> {"ABC"=>"15", "LOP"=>"22"}
A more orthodox approach without tricks on the order of the keys:
groups = h.group_by { |k, v| k[1..-1].to_i }
Hash[groups.map do |id, pairs|
h2 = Hash[pairs]
h2.values_at("P#{id}", "R#{id}")
end]
#=> {"ABC"=>"15", "LOP"=>"22"}
One more option:
Hash[h.keys.grep(/P\d+/).map {|k| [h[k], h[k.tr('P','R')]] }]
h = {"P1" => "ABC", "R2" => "22", "R1" => "15", "P2" => "LOP"}
Hash[*h.sort_by{|k, _| [k[/\d+/].to_i, k[/\D+/]]}.map(&:last)]

Convert SQL result to hash with ID keys with Ruby

I have the following array (SQL result):
[
{:id => 1, :field1 => "one", :field2 => "two"},
{:id => 2, :field1 => "one", :field2 => "two"},
...
]
What I want is:
{
1 => {:field1 => "one", :field2 => "two"},
2 => {:field1 => "one", :field2 => "two"},
...
}
Now I do like the following:
data = {}
result.each do |row|
data[row[:id]] = {:field1 => row[:field1], :field2 => row[:field2]}
end
I'm absolutely sure that's wrong way. What is the best way to do it with Ruby? Is there are any snippet like map or something else?
Hash[arr.map { |h| [h.delete(:id), h] }]
One line :)
hash = arr.clone.each_with_object({}) { |e,res| res[e.delete(:id)] = e }
clone is for not destroying arr variable
Something like this, maybe?
arr = [
{:id => 1, :field1 => "one", :field2 => "two"},
{:id => 2, :field1 => "one", :field2 => "two"}
]
hash = arr.each_with_object({}) do |el, memo|
id = el.delete(:id)
memo[id] = el
end
hash # => {1=>{:field1=>"one", :field2=>"two"}, 2=>{:field1=>"one", :field2=>"two"}}

Resources