在Ruby中,如何将一个数组添加到另一个数组中,而不会得到多维度的结果?

我试着:

somearray = ["some", "thing"]
anotherarray = ["another", "thing"]
somearray.push(anotherarray.flatten!)

我预期的

["some", "thing", "another", "thing"]

但有

["some", "thing", nil]
490418 次浏览

您可以使用+操作符!

irb(main):001:0> a = [1,2]
=> [1, 2]
irb(main):002:0> b = [3,4]
=> [3, 4]
irb(main):003:0> a + b
=> [1, 2, 3, 4]
你可以在这里阅读关于数组类的所有内容: # EYZ0 < / p >
["some", "thing"] + ["another", "thing"]

试试这个,它将结合你的数组删除重复

array1 = ["foo", "bar"]
array2 = ["foo1", "bar1"]


array3 = array1|array2

http://www.ruby-doc.org/core/classes/Array.html

进一步的文档请参阅“Set Union”

这里有两种方法,注意在这个例子中,第一种方法分配一个新数组(转换为somearray = somearray + anotherarray)

somearray = ["some", "thing"]


anotherarray = ["another", "thing"]


somearray += anotherarray # => ["some", "thing", "another", "thing"]


somearray = ["some", "thing"]
somearray.concat anotherarray # => ["some", "thing", "another", "thing"]

你已经有了一个可行的想法,但#flatten!在错误的地方——它压扁了它的接收器,所以你可以用它把[1, 2, ['foo', 'bar']]变成[1,2,'foo','bar']

我无疑忘记了一些方法,但你可以连接:

a1.concat a2
a1 + a2              # creates a new array, as does a1 += a2

或# EYZ0:

a1.push(*a2)         # note the asterisk
a2.unshift(*a1)      # note the asterisk, and that a2 is the receiver

或# EYZ0:

a1[a1.length, 0] = a2
a1[a1.length..0] = a2
a1.insert(a1.length, *a2)

或# EYZ0:

(a1 << a2).flatten!  # a call to #flatten instead would return a new array

我发现更容易推入或追加数组,然后将它们压平,如下所示:

somearray = ["some", "thing"]
anotherarray = ["another", "thing"]
somearray.push anotherarray # => ["some", "thing", ["another", "thing"]]
#or
somearray << anotherarray # => ["some", "thing", ["another", "thing"]]
somearray.flatten!  # => ["some", "thing", "another", "thing"]
somearray # => ["some", "thing", "another", "thing"]

最简洁的方法是使用数组# concat方法;它不会创建一个新数组(不像array# +会做同样的事情,但创建一个新数组)。

直接从文档(http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-concat):

concat (other_ary)

将other_ary的元素追加到self。

所以

[1,2].concat([3,4])  #=> [1,2,3,4]

如果将数组# concat作为参数传入,则它将不会平展多维数组。你需要单独处理:

arr= [3,[4,5]]
arr= arr.flatten   #=> [3,4,5]
[1,2].concat(arr)  #=> [1,2,3,4,5]

最后,您可以使用我们的corelib gem (https://github.com/corlewsolutions/corelib),它为Ruby核心类添加了有用的帮助程序。特别地,我们有一个数组# add_all方法,它将在执行concat之前自动平展多维数组。

如果新数据可以是数组或标量,并且如果它是数组,则希望防止新数据嵌套,splat操作符非常棒!它为标量返回一个标量,为数组返回一个已解压的参数列表。

1.9.3-p551 :020 > a = [1, 2]
=> [1, 2]
1.9.3-p551 :021 > b = [3, 4]
=> [3, 4]
1.9.3-p551 :022 > c = 5
=> 5
1.9.3-p551 :023 > a.object_id
=> 6617020
1.9.3-p551 :024 > a.push *b
=> [1, 2, 3, 4]
1.9.3-p551 :025 > a.object_id
=> 6617020
1.9.3-p551 :026 > a.push *c
=> [1, 2, 3, 4, 5]
1.9.3-p551 :027 > a.object_id
=> 6617020
(array1 + array2).uniq

这样你就可以先得到array1元素。你不会得到副本。

本质上,问题是“如何在Ruby中连接数组”。自然,答案是使用concat+,几乎在每个答案中都提到过。

对这个问题的自然扩展是“如何在Ruby中按行执行2D数组的连接”。当我在谷歌上搜索“红宝石串联矩阵”时,这个SO问题是最上面的结果,所以我想我应该把我的答案留给后人(没有问过但相关的)。


在一些应用程序中,你可能想要按行“连接”两个2D数组。类似的,

[[a, b], | [[x],    [[a, b, x],
[c, d]] |  [y]] =>  [c, d, y]]

这有点像“增广”矩阵。例如,我使用这种技术创建了一个邻接矩阵来表示一组较小的矩阵中的图。如果没有这种技术,我将不得不以一种容易出错或令人沮丧的方式迭代组件。例如,我可能不得不使用each_with_index。相反,我将邮政编码组合在一起,如下所示:

# given two multi-dimensional arrays that you want to concatenate row-wise
m1 = [[:a, :b], [:c, :d]]
m2 = [[:x], [:y]]


m1m2 = m1.zip(m2).map(&:flatten)
# => [[:a, :b, :x], [:c, :d, :y]]

适用于Ruby版本>= 2.0但不适用于旧版本的简单方法:

irb(main):001:0> a=[1,2]
=> [1, 2]
irb(main):003:0> b=[3,4]
=> [3, 4]
irb(main):002:0> c=[5,6]
=> [5, 6]
irb(main):004:0> [*a,*b,*c]
=> [1, 2, 3, 4, 5, 6]

我很惊讶没有人提到reduce,当你有一个数组的数组时,它工作得很好:

lists = [["a", "b"], ["c", "d"]]
flatlist = lists.reduce(:+)  # ["a", "b", "c", "d"]

根据@Pilcrow的回答,对于大型数组,唯一合适的答案是concat (+),因为它速度很快,并且在循环中操作时不会分配一个新对象来进行垃圾回收。

下面是基准:

require 'benchmark'


huge_ary_1 = Array.new(1_000_000) { rand(5_000_000..30_000_00) }


huge_ary_2 = Array.new(1_000_000) { rand(35_000_000..55_000_00) }


Benchmark.bm do |bm|
p '-------------------CONCAT ----------------'
bm.report { huge_ary_1.concat(huge_ary_2) }


p '------------------- PUSH ----------------'
bm.report { huge_ary_1.push(*huge_ary_2)  }
end

结果:

       user     system      total        real
"-------------------CONCAT ----------------"
0.000000   0.000000   0.000000 (  0.009388)
"------------------- PUSH ----------------"
example/array_concat_vs_push.rb:13:in `block (2 levels) in <main>': stack level too deep (SystemStackError)

正如您所看到的,当数组足够大时,使用push会抛出错误: stack level too deep (SystemStackError)

只是另一种方法。

[somearray, anotherarray].flatten
=> ["some", "thing", "another", "thing"]
a = ['a', 'b']
b = ['c', 'd']
arr = [a, b].flatten

这不会去除dups,但是

a|b

删除重复。

a = ["some", "thing"]
b = ["another", "thing"]

b附加到a,并将结果存储在a中:

a.push(*b)

a += b

在任何一种情况下,a变成:

["some", "thing", "another", "thing"]

但在前一种情况下,b的元素被追加到现有的a数组中,在后一种情况下,两个数组连接在一起,结果存储在a中。

Somearray = ["some", "thing"]

Anotherarray = ["another", "thing"]

Somearray + anotherarray

somearray = ["some", "thing"]
anotherarray = ["another", "thing"]
somearray + anotherarray # => ["some", "thing", "another", "thing"]
somearray.concat anotherarray # => ["some", "thing", "another", "thing"]
somearray.push(anotherarray).flatten # => ["some", "thing", "another", "thing"]
somearray.push *anotherarray # => ["another", "thing", "another", "thing"]