【问题标题】:Adding parameters to Array Product function in Ruby在 Ruby 中将参数添加到 Array Product 函数
【发布时间】:2017-08-16 02:34:33
【问题描述】:

所以我一直在摸索着寻找解决方案。

我需要一种方法,该方法将获取我需要收集的product 的任意数量的数组。

1 个数组:

return [A, B, C] # => [A, B, C]

2 个数组:

return [A, B, C].product([1, 2, 3]) # => [[A, 1], [A, 2], [A, 3], [B, 1] ... [C, 3]]

3 个数组:

return [A, B, C].product([1, 2, 3,],[x, y, z]) # => [[A, 1, x], [A, 1, y], ... [C, 3, z]]

所以我目前的解决方案是这种情况下的开关,它是功能性的,但不方便。

case options.count
when 1
  options[0].values
when 2
  options[0].values.product(options[1].values)
when 3
  options[0].values.product(options[1].values,
                            options[2].values)
when 4
  options[0].values.product(options[1].values,
                            options[2].values,
                            options[3].values)
end

我正在寻找的是一种以程序方式或递归方式返回未知数量数组的乘积的方法。输出需要像上面的数组一样。

我试过了:

array = options[0].values
options.each_with_index do |option, i|
  array = array.product(option.values) if i > 0
end
return array

但它会返回:

[[[A, 1], x], [[A, 1], y], [[A, 1], z], [[A, 2], x], ... [[C, 3], z]]

哪个值分组不正确。

【问题讨论】:

  • 我对这个问题有点困惑。你不是在描述内置的product 方法吗?您正在寻找的东西有何不同?也许我是误会了。如果您正在寻找的是 [1,2].product([3,4], [5,6]) # => [[1,3,5],[1,3,6],[1,4,5],[1,4,6], ...],那正是 product 所做的
  • 我有可变数量的数组要通过 product 方法,并且不知道数组的 * 前缀将其分隔为不同的参数,而不是数组成为第一个论据。

标签: arrays ruby


【解决方案1】:

怎么样:

def multi_product(base, *args)
  base.product(*args)
end

结果:

multi_product(['A', 'B', 'C'])
# => [["A"], ["B"], ["C"]]
multi_product(['A', 'B', 'C'], [1, 2, 3])
# => [["A", 1], ["A", 2], ["A", 3], ["B", 1], ["B", 2], ["B", 3], ["C", 1], ["C", 2], ["C", 3]]
multi_product(['A', 'B', 'C'], [1, 2, 3], ['x', 'y', 'z'])
# => [["A", 1, "x"], ["A", 1, "y"], ["A", 1, "z"], ["A", 2, "x"], ["A", 2, "y"], ["A", 2, "z"], ["A", 3, "x"], ["A", 3, "y"], ["A", 3, "z"], ["B", 1, "x"], ["B", 1, "y"], ["B", 1, "z"], ["B", 2, "x"], ["B", 2, "y"], ["B", 2, "z"], ["B", 3, "x"], ["B", 3, "y"], ["B", 3, "z"], ["C", 1, "x"], ["C", 1, "y"], ["C", 1, "z"], ["C", 2, "x"], ["C", 2, "y"], ["C", 2, "z"], ["C", 3, "x"], ["C", 3, "y"], ["C", 3, "z"]]
multi_product(['A', 'B', 'C'], [1, 2, 3], ['x', 'y', 'z'], [4, 5, 6])
# => [["A", 1, "x", 4], ["A", 1, "x", 5], ["A", 1, "x", 6], ["A", 1, "y", 4], ["A", 1, "y", 5], ["A", 1, "y", 6], ["A", 1, "z", 4], ["A", 1, "z", 5], ["A", 1, "z", 6], ["A", 2, "x", 4], ["A", 2, "x", 5], ["A", 2, "x", 6], ["A", 2, "y", 4], ["A", 2, "y", 5], ["A", 2, "y", 6], ["A", 2, "z", 4], ["A", 2, "z", 5], ["A", 2, "z", 6], ["A", 3, "x", 4], ["A", 3, "x", 5], ["A", 3, "x", 6], ["A", 3, "y", 4], ["A", 3, "y", 5], ["A", 3, "y", 6], ["A", 3, "z", 4], ["A", 3, "z", 5], ["A", 3, "z", 6], ["B", 1, "x", 4], ["B", 1, "x", 5], ["B", 1, "x", 6], ["B", 1, "y", 4], ["B", 1, "y", 5], ["B", 1, "y", 6], ["B", 1, "z", 4], ["B", 1, "z", 5], ["B", 1, "z", 6], ["B", 2, "x", 4], ["B", 2, "x", 5], ["B", 2, "x", 6], ["B", 2, "y", 4], ["B", 2, "y", 5], ["B", 2, "y", 6], ["B", 2, "z", 4], ["B", 2, "z", 5], ["B", 2, "z", 6], ["B", 3, "x", 4], ["B", 3, "x", 5], ["B", 3, "x", 6], ["B", 3, "y", 4], ["B", 3, "y", 5], ["B", 3, "y", 6], ["B", 3, "z", 4], ["B", 3, "z", 5], ["B", 3, "z", 6], ["C", 1, "x", 4], ["C", 1, "x", 5], ["C", 1, "x", 6], ["C", 1, "y", 4], ["C", 1, "y", 5], ["C", 1, "y", 6], ["C", 1, "z", 4], ["C", 1, "z", 5], ["C", 1, "z", 6], ["C", 2, "x", 4], ["C", 2, "x", 5], ["C", 2, "x", 6], ["C", 2, "y", 4], ["C", 2, "y", 5], ["C", 2, "y", 6], ["C", 2, "z", 4], ["C", 2, "z", 5], ["C", 2, "z", 6], ["C", 3, "x", 4], ["C", 3, "x", 5], ["C", 3, "x", 6], ["C", 3, "y", 4], ["C", 3, "y", 5], ["C", 3, "y", 6], ["C", 3, "z", 4], ["C", 3, "z", 5], ["C", 3, "z", 6]]

它的作用是采用一个响应product 的必需参数(base),然后*args 采用可变数量的其他参数并将它们存储在一个数组中 args 。然后,您可以使用 * 将数组解构回参数列表,这是在对 product(*args) 的调用中完成的,因此(在第二个示例的情况下)最终看起来像

['A', 'B', 'C'].product([1, 2, 3], ['x', 'y', 'z'])

【讨论】:

  • 感谢您的回答。我缺少的一条信息是将* 放在一个数组前面,将它分成多个方法参数。
【解决方案2】:

希望对你有帮助

a =  [["a", "b", "c"], ["d", "e", "f"], ["g", "h", "i"]]
a[0].product(*a[1..a.length])
#=> [["a", "d", "g"], ["a", "d", "h"], ["a", "d", "i"], ["a", "e", "g"], ["a", "e", "h"], ["a", "e", "i"], ["a", "f", "g"], ["a", "f", "h"], ["a", "f", "i"], ["b", "d", "g"], ["b", "d", "h"], ["b", "d", "i"], ["b", "e", "g"], ["b", "e", "h"], ["b", "e", "i"], ["b", "f", "g"], ["b", "f", "h"], ["b", "f", "i"], ["c", "d", "g"], ["c", "d", "h"], ["c", "d", "i"], ["c", "e", "g"], ["c", "e", "h"], ["c", "e", "i"], ["c", "f", "g"], ["c", "f", "h"], ["c", "f", "i"]]
# or 
a.slice!(0).product(*a) #Note: this mutates array.
# or
a[0].product(*a.drop(1)) # suggested by Cary Swoveland

【讨论】:

  • 考虑使用a.first 而不是a[0]:)
  • @engineersmnky :没有得到最后一部分 - 它不会产生影响? a.shift 以后会改成*a,我想;就像a.slice!(0) 一样。没有?
  • @kiddorails 我的道歉应该是def multi_product(*a); a.shift.product(*a); end 然后称为multi_product(*a) 因为splat 将创建一个新的Array 原始a 不会被修改。此外,您可以选择def multi_product(a); first,*rest = a; first.product(*rest);end
  • 你可以使用*a.drop(1)作为参数。
  • 我接受这个作为答案,因为在我的特殊情况下看到它在这些建议中阐明了更多。
猜你喜欢
  • 2011-06-28
  • 2019-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多