如何将一个数组添加到Ruby中的另一个数组中,而不是以一个多维的结果结束?

时间:2022-08-24 07:33:28
somearray = ["some", "thing"]

anotherarray = ["another", "thing"]

somearray.push(anotherarray.flatten!)

I expected

我预期的

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

14 个解决方案

#1


567  

You've got a workable idea, but the #flatten! is in the wrong place -- it flattens its receiver, so you could use it to turn [1, 2, ['foo', 'bar']] into [1,2,'foo','bar'].

你有一个可行的主意,但这是不可能的!在错误的地方——它使接收器变平,所以你可以用它来把[1,2,['foo', 'bar']变成[1,2,'foo','bar']。

I'm doubtless forgetting some approaches, but you can concatenate:

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

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

or prepend/append:

或预先考虑/追加:

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

or splice:

或接头:

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

or append and flatten:

或附加平:

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

#2


176  

You can just use the + operator!

你可以使用+运算符!

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]

You can read all about the array class here: http://ruby-doc.org/core/classes/Array.html

您可以在这里阅读所有关于数组类的内容:http://ruby-doc.org/core/classes/Array.html。

#3


55  

The cleanest approach is to use the Array#concat method; it will not create a new array (unlike Array#+ which will do the same thing but create a new array).

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

Straight from the docs (http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-concat):

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

concat(other_ary)

Appends the elements of other_ary to self.

将其他元素附加到self。

So

所以

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

Array#concat will not flatten a multidimensional array if it is passed in as an argument. You'll need to handle that separately:

数组#concat如果作为参数传入,则不会使多维数组变平。你需要分开处理:

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

Lastly, you can use our corelib gem (https://github.com/corlewsolutions/corelib) which adds useful helpers to the Ruby core classes. In particular we have an Array#add_all method which will automatically flatten multidimensional arrays before executing the concat.

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

#4


26  

Try this, it will combine your arrays removing duplicates

尝试一下,它将组合您的数组删除重复。

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

array3 = array1|array2

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

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

Further documentation look at "Set Union"

进一步的文档查看“Set Union”

#5


24  

Here are two ways, notice in this case that the first way returns a new array ( translates to somearray = somearray + anotherarray )

这里有两种方法,注意在这种情况下,第一种方法返回一个新数组(转换为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"]

#6


24  

Easy method that works with Ruby version >= 2.0 but not with older versions :

使用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]

#7


15  

(array1 + array2).uniq

(array1 + array2).uniq

This way you get array1 elements first. You will get no duplicates.

这样就得到了array1元素。你不会得到重复。

#8


5  

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

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

#9


5  

The question, essentially, is "how to concatenate arrays in Ruby". Naturally the answer is to use concat or + as mentioned in nearly every answer.

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

A natural extension to the question would be "how to perform row-wise concatenation of 2D arrays in Ruby". When I googled "ruby concatenate matrices", this SO question was the top result so I thought I would leave my answer to that (unasked but related) question here for posterity.

对这个问题的自然扩展是“如何在Ruby中执行二维数组的行级连接”。当我在google上搜索“ruby concatenate矩阵”时,这个问题是最重要的,所以我想我应该把我的答案留给子孙后代。


In some applications you might want to "concatenate" two 2D arrays row-wise. Something like,

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

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

This is something like "augmenting" a matrix. For example, I used this technique to create a single adjacency matrix to represent a graph out of a bunch of smaller matrices. Without this technique I would have had to iterate over the components in a way that could have been error prone or frustrating to think about. I might have had to do an each_with_index, for example. Instead I combined zip and flatten as follows,

这类似于“扩大”矩阵。例如,我使用这种技术创建了一个邻接矩阵来表示一组较小矩阵的图形。如果没有这种技术,我将不得不以一种可能出现错误或令人沮丧的方式来迭代这些组件。例如,我可能不得不做一个each_with_index。相反,我把zip和flatten结合起来,

# 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]]

#10


3  

If the new data could be an array or a scalar, and you want to prevent the new data to be nested if it was an array, the splat operator is awesome! It returns a scalar for a scalar, and an unpacked list of arguments for an array.

如果新数据可以是数组或标量,并且您希望防止新数据嵌套,如果它是一个数组,那么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 

#11


2  

I find it easier to push or append arrays and then flatten them in place, like so:

我发现推或追加数组并将它们压平,这样更容易:

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"]

#12


2  

I'm surprised nobody has mentioned reduce, which works well when you have an array of arrays:

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

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

#13


1  

Elaborating on @Pilcrow's answer the only suitable answer for huge arrays is concat since is fast and does not allocate a new object to be garbage-collected when operating inside a loop.

对大数组的唯一合适的回答是“concat”,因为它是快速的,而且在循环中运行时不会分配一个新的对象。

Here's the benchmark:

基准:

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

Results:

结果:

       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)

As you can see using push throws an ERROR: stack level too deep (SystemStackError) when the arrays are big enough.

正如您可以看到的,使用push抛出一个错误:当数组足够大时,堆栈级别太深(SystemStackError)。

#14


0  

Just another way of doing it.

只是另一种方法。

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

#1


567  

You've got a workable idea, but the #flatten! is in the wrong place -- it flattens its receiver, so you could use it to turn [1, 2, ['foo', 'bar']] into [1,2,'foo','bar'].

你有一个可行的主意,但这是不可能的!在错误的地方——它使接收器变平,所以你可以用它来把[1,2,['foo', 'bar']变成[1,2,'foo','bar']。

I'm doubtless forgetting some approaches, but you can concatenate:

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

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

or prepend/append:

或预先考虑/追加:

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

or splice:

或接头:

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

or append and flatten:

或附加平:

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

#2


176  

You can just use the + operator!

你可以使用+运算符!

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]

You can read all about the array class here: http://ruby-doc.org/core/classes/Array.html

您可以在这里阅读所有关于数组类的内容:http://ruby-doc.org/core/classes/Array.html。

#3


55  

The cleanest approach is to use the Array#concat method; it will not create a new array (unlike Array#+ which will do the same thing but create a new array).

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

Straight from the docs (http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-concat):

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

concat(other_ary)

Appends the elements of other_ary to self.

将其他元素附加到self。

So

所以

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

Array#concat will not flatten a multidimensional array if it is passed in as an argument. You'll need to handle that separately:

数组#concat如果作为参数传入,则不会使多维数组变平。你需要分开处理:

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

Lastly, you can use our corelib gem (https://github.com/corlewsolutions/corelib) which adds useful helpers to the Ruby core classes. In particular we have an Array#add_all method which will automatically flatten multidimensional arrays before executing the concat.

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

#4


26  

Try this, it will combine your arrays removing duplicates

尝试一下,它将组合您的数组删除重复。

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

array3 = array1|array2

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

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

Further documentation look at "Set Union"

进一步的文档查看“Set Union”

#5


24  

Here are two ways, notice in this case that the first way returns a new array ( translates to somearray = somearray + anotherarray )

这里有两种方法,注意在这种情况下,第一种方法返回一个新数组(转换为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"]

#6


24  

Easy method that works with Ruby version >= 2.0 but not with older versions :

使用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]

#7


15  

(array1 + array2).uniq

(array1 + array2).uniq

This way you get array1 elements first. You will get no duplicates.

这样就得到了array1元素。你不会得到重复。

#8


5  

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

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

#9


5  

The question, essentially, is "how to concatenate arrays in Ruby". Naturally the answer is to use concat or + as mentioned in nearly every answer.

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

A natural extension to the question would be "how to perform row-wise concatenation of 2D arrays in Ruby". When I googled "ruby concatenate matrices", this SO question was the top result so I thought I would leave my answer to that (unasked but related) question here for posterity.

对这个问题的自然扩展是“如何在Ruby中执行二维数组的行级连接”。当我在google上搜索“ruby concatenate矩阵”时,这个问题是最重要的,所以我想我应该把我的答案留给子孙后代。


In some applications you might want to "concatenate" two 2D arrays row-wise. Something like,

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

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

This is something like "augmenting" a matrix. For example, I used this technique to create a single adjacency matrix to represent a graph out of a bunch of smaller matrices. Without this technique I would have had to iterate over the components in a way that could have been error prone or frustrating to think about. I might have had to do an each_with_index, for example. Instead I combined zip and flatten as follows,

这类似于“扩大”矩阵。例如,我使用这种技术创建了一个邻接矩阵来表示一组较小矩阵的图形。如果没有这种技术,我将不得不以一种可能出现错误或令人沮丧的方式来迭代这些组件。例如,我可能不得不做一个each_with_index。相反,我把zip和flatten结合起来,

# 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]]

#10


3  

If the new data could be an array or a scalar, and you want to prevent the new data to be nested if it was an array, the splat operator is awesome! It returns a scalar for a scalar, and an unpacked list of arguments for an array.

如果新数据可以是数组或标量,并且您希望防止新数据嵌套,如果它是一个数组,那么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 

#11


2  

I find it easier to push or append arrays and then flatten them in place, like so:

我发现推或追加数组并将它们压平,这样更容易:

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"]

#12


2  

I'm surprised nobody has mentioned reduce, which works well when you have an array of arrays:

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

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

#13


1  

Elaborating on @Pilcrow's answer the only suitable answer for huge arrays is concat since is fast and does not allocate a new object to be garbage-collected when operating inside a loop.

对大数组的唯一合适的回答是“concat”,因为它是快速的,而且在循环中运行时不会分配一个新的对象。

Here's the benchmark:

基准:

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

Results:

结果:

       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)

As you can see using push throws an ERROR: stack level too deep (SystemStackError) when the arrays are big enough.

正如您可以看到的,使用push抛出一个错误:当数组足够大时,堆栈级别太深(SystemStackError)。

#14


0  

Just another way of doing it.

只是另一种方法。

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