What I have:
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"]
What I need:
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
- 比特率= 100,fps = 15,qp = 20
-
bitrate = 500
,fps = 15
,qp = 30
- 比特率= 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
?
...为每个可能的组合调用块。我怎么定义foo?
What I (probably) don't need:
Now, I know this: Combine array of array into all possible combinations, forward only, in Ruby, suggesting something like:
现在,我知道这一点:将数组数组合并到所有可能的组合中,仅在Ruby中转发,建议类似于:
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.
但是这只对数组中的值和数组进行操作,我需要对参数名称的原始引用。
3 个解决方案
#1
27
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}]
#2
2
Just FYI I took fl00r's approach and monkey-patched it. I like it a bit better.
仅供参考我采用了fl00r的方法并对其进行了修补。我喜欢它好一点。
class Hash
def product
product = values[0].product(*values[1..-1])
product.map{|p| Hash[keys.zip p]}
end
end
#3
0
I believe fl00r's answer is almost perfect but has a drawback. It assumes that hsh.values
and hsh.keys
will have a matching order, which as far as I know, is not warrantied. So you will probably need an extra step to ensure that. Maybe something like:
我相信fl00r的答案几乎是完美的但有一个缺点。它假定hsh.values和hsh.keys将具有匹配的顺序,据我所知,这是不保证的。因此,您可能需要额外的步骤来确保这一点。也许是这样的:
def product_hash(hsh)
keys = hsh.keys
attrs = keys.map { |key| hsh[key] }
product = attrs[0].product(*attrs[1..-1])
product.map{ |p| Hash[keys.zip p] }
end
But fl00r can correct me if I'm wrong.
但是如果我错了,fl00r可以纠正我。
#1
27
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}]
#2
2
Just FYI I took fl00r's approach and monkey-patched it. I like it a bit better.
仅供参考我采用了fl00r的方法并对其进行了修补。我喜欢它好一点。
class Hash
def product
product = values[0].product(*values[1..-1])
product.map{|p| Hash[keys.zip p]}
end
end
#3
0
I believe fl00r's answer is almost perfect but has a drawback. It assumes that hsh.values
and hsh.keys
will have a matching order, which as far as I know, is not warrantied. So you will probably need an extra step to ensure that. Maybe something like:
我相信fl00r的答案几乎是完美的但有一个缺点。它假定hsh.values和hsh.keys将具有匹配的顺序,据我所知,这是不保证的。因此,您可能需要额外的步骤来确保这一点。也许是这样的:
def product_hash(hsh)
keys = hsh.keys
attrs = keys.map { |key| hsh[key] }
product = attrs[0].product(*attrs[1..-1])
product.map{ |p| Hash[keys.zip p] }
end
But fl00r can correct me if I'm wrong.
但是如果我错了,fl00r可以纠正我。