假设我有这样的哈希值,各种值属于一个参数。
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
预先不知道参数(即键)的数量和值的数量(即值阵列的长度)。理想情况下,我会做类似的事情:
a.foo do |ret|
puts ret.keys # => ["bitrate", "fps", "qp"]
puts ret.values # => ["100", "15", "20"]
end
...为每个可能的组合调用块。如何定义foo
?
现在,我知道这一点:Combine array of array into all possible combinations, forward only, in Ruby,建议像:
a.first.product(*a[1..-1]).map(&:join)
但是这只对数组中的值和数组进行操作,我需要对参数名称的原始引用。
答案 0 :(得分:29)
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}]
答案 1 :(得分:2)
仅供参考我采用了fl00r的方法并对其进行了修补。我喜欢它好一点。
class Hash
def product
product = values[0].product(*values[1..-1])
product.map{|p| Hash[keys.zip p]}
end
end
答案 2 :(得分:1)
请尝试使用OCG选项组合生成器。
require "ocg"
generator = OCG.new(
:bitrate => %w[100 500 1000],
:fps => %w[15 30],
:qp => %w[20 30]
)
puts generator.next until generator.finished?
Generator包含更多功能,可帮助您处理其他选项。
答案 3 :(得分:0)
我相信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可以纠正我。