Ruby中数组哈希的所有可能组合
是)我有的:
假设我有这样的哈希值,各种值属于一个参数。
a = {} a[:bitrate] = ["100", "500", "1000"] a[:fps] = ["15", "30"] a[:qp] = ["20", "30"]
我需要的:
我需要一些方法来迭代地获得这些值的所有可能组合,因此,使用所有参数/值对:
-
bitrate = 100
,fps = 15
,qp = 20
-
bitrate = 500
,fps = 15
,qp = 30
- …
参数的数量(即键)和值的数量(即值arrays的长度)事先是未知的。 理想情况下,我会做类似的事情:
a.foo do |ret| puts ret.keys # => ["bitrate", "fps", "qp"] puts ret.values # => ["100", "15", "20"] end
…为每个可能的组合调用块。 我怎么定义foo
?
我(可能)不需要的东西:
现在,我知道这一点:将数组数组合并到所有可能的组合中,仅在Ruby中转发 ,建议类似于:
a.first.product(*a[1..-1]).map(&:join)
但是这只对数组中的值和数组进行操作,我需要对参数名称的原始引用。
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)
你会得到
[{: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"}]
您还可以向哈希添加新密钥。
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}]
仅供参考我采用了fl00r的方法并对其进行了修补。 我喜欢它好一点。
class Hash def product product = values[0].product(*values[1..-1]) product.map{|p| Hash[keys.zip p]} end end
我相信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
但是如果我错了,fl00r可以纠正我。