Let's say I have a hash like this, with various values belonging to one parameter.
a = {}
a[:bitrate] = ["100", "500", "1000"]
a[:fps] = ["15", "30"]
a[:qp] = ["20", "30"]
I need some way to iteratively get all the possible combinations of these values, so, with all the parameter/value pairs:
bitrate = 100
, fps = 15
, qp = 20
bitrate = 500
, fps = 15
, qp = 30
The number of parameters (i.e. the keys) and the number of values (i.e. the length of the value arrays) are not known beforehand. Ideally, I'd do something like:
a.foo do |ret|
puts ret.keys # => ["bitrate", "fps", "qp"]
puts ret.values # => ["100", "15", "20"]
end
… where the block is called for each possible combination. How can I define foo
?
Now, I know this: Combine array of array into all possible combinations, forward only, in Ruby, suggesting something like:
a.first.product(*a[1..-1]).map(&:join)
But this operates on values and arrays in arrays only, and I need the original reference to the parameter's name.
Each key can only have one value. But the same value can occur more than once inside a Hash, while each key can occur only once.
We can merge two hashes using the merge() method. When using the merge() method: Each new entry is added to the end. Each duplicate-key entry's value overwrites the previous value.
Ruby's arrays and hashes are indexed collections. Both store collections of objects, accessible using a key. With arrays, the key is an integer, whereas hashes support any object as a key.
a = {}
a[:bitrate] = ["100", "500", "1000"]
a[:fps] = ["15", "30"]
a[:qp] = ["20", "30"]
def product_hash(hsh)
attrs = hsh.values
keys = hsh.keys
product = attrs[0].product(*attrs[1..-1])
product.map{ |p| Hash[keys.zip p] }
end
product_hash(a)
you'll get
[{:bitrate=>"100", :fps=>"15", :qp=>"20"},
{:bitrate=>"100", :fps=>"15", :qp=>"30"},
{:bitrate=>"100", :fps=>"30", :qp=>"20"},
{:bitrate=>"100", :fps=>"30", :qp=>"30"},
{:bitrate=>"500", :fps=>"15", :qp=>"20"},
{:bitrate=>"500", :fps=>"15", :qp=>"30"},
{:bitrate=>"500", :fps=>"30", :qp=>"20"},
{:bitrate=>"500", :fps=>"30", :qp=>"30"},
{:bitrate=>"1000", :fps=>"15", :qp=>"20"},
{:bitrate=>"1000", :fps=>"15", :qp=>"30"},
{:bitrate=>"1000", :fps=>"30", :qp=>"20"},
{:bitrate=>"1000", :fps=>"30", :qp=>"30"}]
You can also add new key to your hash.
a = {}
a[:bitrate] = ["100", "500", "1000"]
a[:fps] = ["15", "30"]
a[:qp] = ["20", "30"]
a[:bw] = [true, false]
product_hash(a)
#=>
[{:bitrate=>"100", :fps=>"15", :qp=>"20", :bw=>true},
{:bitrate=>"100", :fps=>"15", :qp=>"20", :bw=>false},
{:bitrate=>"100", :fps=>"15", :qp=>"30", :bw=>true},
{:bitrate=>"100", :fps=>"15", :qp=>"30", :bw=>false},
{:bitrate=>"100", :fps=>"30", :qp=>"20", :bw=>true},
{:bitrate=>"100", :fps=>"30", :qp=>"20", :bw=>false},
{:bitrate=>"100", :fps=>"30", :qp=>"30", :bw=>true},
{:bitrate=>"100", :fps=>"30", :qp=>"30", :bw=>false},
{:bitrate=>"500", :fps=>"15", :qp=>"20", :bw=>true},
{:bitrate=>"500", :fps=>"15", :qp=>"20", :bw=>false},
{:bitrate=>"500", :fps=>"15", :qp=>"30", :bw=>true},
{:bitrate=>"500", :fps=>"15", :qp=>"30", :bw=>false},
{:bitrate=>"500", :fps=>"30", :qp=>"20", :bw=>true},
{:bitrate=>"500", :fps=>"30", :qp=>"20", :bw=>false},
{:bitrate=>"500", :fps=>"30", :qp=>"30", :bw=>true},
{:bitrate=>"500", :fps=>"30", :qp=>"30", :bw=>false},
{:bitrate=>"1000", :fps=>"15", :qp=>"20", :bw=>true},
{:bitrate=>"1000", :fps=>"15", :qp=>"20", :bw=>false},
{:bitrate=>"1000", :fps=>"15", :qp=>"30", :bw=>true},
{:bitrate=>"1000", :fps=>"15", :qp=>"30", :bw=>false},
{:bitrate=>"1000", :fps=>"30", :qp=>"20", :bw=>true},
{:bitrate=>"1000", :fps=>"30", :qp=>"20", :bw=>false},
{:bitrate=>"1000", :fps=>"30", :qp=>"30", :bw=>true},
{:bitrate=>"1000", :fps=>"30", :qp=>"30", :bw=>false}]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With