Ruby中数组哈希的所有可能组合
Posted
技术标签:
【中文标题】Ruby中数组哈希的所有可能组合【英文标题】:All possible combinations from a hash of arrays in Ruby 【发布时间】:2012-04-04 21:19:14 【问题描述】:我有什么:
假设我有一个像这样的散列,不同的值属于一个参数。
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)
但这仅对数组中的值和数组起作用,我需要对参数名称的原始引用。
【问题讨论】:
【参考方案1】: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]
【讨论】:
【参考方案2】:仅供参考,我采用了 fl00r 的方法并对其进行了猴子修补。我更喜欢它。
class Hash
def product
product = values[0].product(*values[1..-1])
product.map|p| Hash[keys.zip p]
end
end
【讨论】:
【参考方案3】:请尝试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?
生成器包含更多功能,可帮助您处理其他选项。
【讨论】:
【参考方案4】:我相信 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 可以纠正我。
【讨论】:
对于 Ruby >= 1.9,它们的顺序相同 这是由语言规范或仅适用于 MRI 的东西所保证的吗?在这两种情况下,您能否请我指出确保这一点的文档?我永远不知道在哪里可以找到这样的东西。谢谢。 ruby-doc.org/core-2.4.1/Hash.htmlHashes enumerate their values in the order that the corresponding keys were inserted.
以上是关于Ruby中数组哈希的所有可能组合的主要内容,如果未能解决你的问题,请参考以下文章