Ruby: 如何将数组中的数组连接成一个数组

82

我在Ruby on Rails(3.1)中有一个数组,其中所有内部数组的大小都不同。有没有一种简单的方法将所有内部数组连接起来,获得一个大小为一的大数组,其中包含所有项?

我知道可以使用Array :: concat函数将两个数组连接起来,并且我可以使用循环按顺序将它们连接起来,如下所示:

concatenated = Array.new
array_of_arrays.each do |array|
    concatenated.concat(array)
end

但我想知道是否有一种Ruby的单行代码可以更清晰地完成它。

谢谢你的帮助。


1
如建议所示,flatten(1) 是你想要的,但我想指出你也可以将上述内容写为 array_of_arrays.reduce(:concat) - Cary Swoveland
3个回答

183
你需要使用#flatten方法:
concatenated = array_of_arrays.flatten

默认情况下,这将递归地展平列表。 #flatten 接受一个可选参数来限制递归深度 - 文档列出了例子以说明区别。


24
更好的“flatten(1)”功能。数组中的元素也可能是数组本身,它们将被递归地展平。 - tokland
顺便提一下,可选参数需要 Ruby 1.8.7 或更高版本。 - user102008
另外,作为一般建议;建议使用flatten!(n),因为它会直接修改对象而不是复制它。使用修改对象的方法可以通过减少需要执行的GC数量来提高性能。 - ARun32
1
  1. 这是相当强大的死灵法术:D
  2. 我不会把它作为一个普遍的建议,特别是现在函数式编程已经成为一种模因。但即使忽略这一点,我认为通常破坏输入是不好的,引用透明度是好的,并且应该在可观察结果与使用副本相同的情况下使用bang方法作为优化,除非你有基于程序逻辑的原因想要暴露原地突变。
- millimoose

30

更一般地说:

array_of_arrays.reduce(:concat)

这不会像#flatten方法那样破坏3、4或5+维数组;使用#flatten时,您需要非常注意数组的内容,因为它是一种递归方法,可能有利也可能有害。 - d11wtq
啊,好的。如果我用它来做类似的事情,我会记住这一点的。在这种情况下,这并不是非常重要,因为它们只是简单的数组,递归可以正常工作。 - Pedro Cori
@d11wtq:没错,这就是为什么 Ruby 1.9 有 flatten(n) - tokland
2
请注意,此代码将更改原始的array_of_arrays,如果您仍计划在其他地方使用原始数组,则可能会导致问题。 - mkataja
为了避免改变原始数组,你可以使用 array_of_arrays.reduce :+。但请注意,如果 array_of_arrays 为空,则这两个方法都会返回 nil,而 flatten 方法则会返回 [] - Tim Smith

6
你可以使用flatten!方法。例如。 a = [1, 2, [3, [4, 5]]] a.flatten! #=> [1, 2, 3, 4, 5]

通过使用 a.flatten!,您还可以防止创建数组的副本,从而节省内存和垃圾回收。 - ARun32

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接