简体   繁体   English

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

[英]How do you add an array to another array in Ruby and not end up with a multi-dimensional result?

somearray = ["some", "thing"]

anotherarray = ["another", "thing"]

somearray.push(anotherarray.flatten!)

I expected我期望

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

You've got a workable idea, but the #flatten!你有一个可行的想法,但#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

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

The cleanest approach is to use the Array#concat method;最干净的方法是使用Array#concat方法; it will not create a new array (unlike Array#+ which will do the same thing but create a new array).它不会创建一个新数组(与 Array#+ 不同,它会做同样的事情但会创建一个新数组)。

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)连接(other_ary)

Appends the elements of other_ary to self.将 other_ary 的元素附加到 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.如果将多维数组作为参数传入,则Array#concat不会展平多维数组。 You'll need to handle that separately:您需要单独处理:

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.最后,您可以使用我们的 corelib gem ( https://github.com/corlewsolutions/corelib ),它为 Ruby 核心类添加了有用的帮助程序。 In particular we have an Array#add_all method which will automatically flatten multidimensional arrays before executing the concat.特别是我们有一个Array#add_all方法,它会在执行 concat 之前自动展平多维数组。

Here are two ways, notice in this case that the first way assigns 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"]

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]
a = ["some", "thing"]
b = ["another", "thing"]

To append b to a and store the result in a :b附加到a并将结果存储在a

a.push(*b)

or要么

a += b

In either case, a becomes:在任何一种情况下, a变成:

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

but in the former case, the elements of b are appended to the existing a array, and in the latter case the two arrays are concatenated together and the result is stored in a .但在前一种情况下, b的元素被附加到现有的a数组中,在后一种情况下,两个数组连接在一起,结果存储在a

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"进一步的文档查看“设置联合”

(array1 + array2).uniq

This way you get array1 elements first.这样你首先得到 array1 元素。 You will get no duplicates.你不会得到重复。

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.详细说明@Pilcrow 的答案,对于大数组唯一合适的答案是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会抛出一个ERROR : stack level too deep (SystemStackError)

Just another way of doing it.只是另一种方式。

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

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

The question, essentially, is "how to concatenate arrays in Ruby".问题本质上是“如何在 Ruby 中连接数组”。 Naturally the answer is to use concat or + as mentioned in nearly every answer.自然地,答案是使用concat+ ,几乎在每个答案中都提到过。

A natural extension to the question would be "how to perform row-wise concatenation of 2D arrays in Ruby".这个问题的一个自然扩展是“如何在 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.当我在 google 上搜索“ruby concatenate matrices”时,这个 SO 问题是最高的结果,所以我想我会把我对那个(未提出但相关的)问题的答案留给后代。


In some applications you might want to "concatenate" two 2D arrays row-wise.在某些应用程序中,您可能希望按行“连接”两个二维数组。 Something like,就像是,

[[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.例如,我可能不得不执行each_with_index Instead I combined zip and flatten as follows,相反,我将zipflatten组合如下,

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

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!如果新数据可以是数组或标量,并且您想防止新数据被嵌套(如果它是数组),那么 splat 运算符就很棒! It returns a scalar for a scalar, and an unpacked list of arguments for an array.它为标量返回一个标量,并为数组返回一个解压缩的参数列表。

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 
a = ['a', 'b']
b = ['c', 'd']
arr = [a, b].flatten

This won't remove dups, but这不会删除重复项,但是

a|b

removes dups.删除重复项。

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

somearray = ["some", "thing"] somearray = [“一些”,“东西”]

anotherarray = ["another", "thing"] anotherarray = [“另一个”,“东西”]

somearray + anotherarray一些数组 + 另一个数组

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM