Ruby中两个数组的组合


82

Ruby实现跟踪的方式是什么?

a = [1,2]
b = [3,4]

我想要一个数组:

=> [f(1,3) ,f(1,4) , f(2,3) ,f(2,4)]

@lucasarruda与OP要求的不完全相同。Zip将创建一个[a[0], b[0]]和的数组[a[1], b[1]]。不包括[a[0], b[1]]a.zip(b) => [[1,3],[2,4]]
KNejad

谢谢@KNejad,您是正确的。删除了我的评论。
lucasarruda

Answers:


147

您可以使用product来先获取数组的笛卡尔积,然后收集函数结果。

a.product(b) => [[1, 3], [1, 4], [2, 3], [2, 4]]

因此,您可以使用mapcollect获取结果。它们是同一方法的不同名称。

a.product(b).collect { |x, y| f(x, y) }

产品仅从1.9开始内置。
香蒜酱

7
产品是1.8.7 -我用它做什么Pierr是问
克里斯·麦考利

1
@FloatingRock是不正确的组合而不是置换。参见ruby-doc.org/core-2.1.3/Array.html#method-i-product
Josh Diehl

1
@FloatingRock不是。每个项目的第一个元素将始终来自第一个列表,第二个元素则来自第二个列表,依此类推。这是元素的所有可能组合,但它们从未重新排序,因此不是排列。
马克·里德

如果您有c = [5,6]和d = [7,8],则可以这样做[a,b,c,d].reduce([[]]){|r,e| r=r.product(e)}.map{|x| x.flatten}
xxjjnn

11
a.map {|x| b.map {|y| f(x,y) } }.flatten

注意:在1.8.7+上,您可以添加1参数作为flatten,因此f返回数组时仍会得到正确的结果。

这是任意数量的数组的抽象:

def combine_arrays(*arrays)
  if arrays.empty?
    yield
  else
    first, *rest = arrays
    first.map do |x|
      combine_arrays(*rest) {|*args| yield x, *args }
    end.flatten
      #.flatten(1)
  end
end

combine_arrays([1,2,3],[3,4,5],[6,7,8]) do |x,y,z| x+y+z end
# => [10, 11, 12, 11, 12, 13, 12, 13, 14, 11, 12, 13, 12, 13, 14, 13, 14, 15, 12, 13, 14, 13, 14, 15, 14, 15, 16]

尽管我不确定这是否是最好的方法(尽管无法想到一个更好的方法,所以+1),这将起作用
罗伯特·马赛利

我希望我可以+2来组合任意数量的数组。很酷!
pierrotlefou

我也想出了这一点..但后来我知道应该有一种更简单的方法...为此+1,但@Aaron Hinni回答了它的清洁问题
奥兰多

5

Facets具有Array#product可为您提供数组叉积的功能。** operator对于两阵列情况,它也被别名为。使用它,它看起来像这样:

require 'facets/array'
a = [1,2]
b = [3,4]

(a.product b).collect {|x, y| f(x, y)}

如果您使用的是Ruby 1.9,product则是内置的Array函数。


人们为什么总是说Array#product是1.9ism?至少在1.8.7中。
Mark Reed 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.