繁体   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!)

我期望

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

前置/附加

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

拼接

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

追加和展平

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

您可以只使用+运算符!

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]

您可以在此处阅读有关数组类的所有信息: http : //ruby-doc.org/core/classes/Array.html

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

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

连接(other_ary)

将 other_ary 的元素附加到 self.

所以

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

如果将多维数组作为参数传入,则Array#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 核心类添加了有用的帮助程序。 特别是我们有一个Array#add_all方法,它会在执行 concat 之前自动展平多维数组。

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

适用于 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"]

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

a.push(*b)

要么

a += b

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

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

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

试试这个,它会结合你的数组去除重复项

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

array3 = array1|array2

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

进一步的文档查看“设置联合”

(array1 + array2).uniq

这样你首先得到 array1 元素。 你不会得到重复。

详细说明@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会抛出一个ERROR : stack level too deep (SystemStackError)

只是另一种方式。

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

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

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

这个问题的一个自然扩展是“如何在 Ruby 中执行二维数组的行级连接”。 当我在 google 上搜索“ruby concatenate matrices”时,这个 SO 问题是最高的结果,所以我想我会把我对那个(未提出但相关的)问题的答案留给后代。


在某些应用程序中,您可能希望按行“连接”两个二维数组。 就像是,

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

这有点像“增强”矩阵。 例如,我使用这种技术创建了一个单一的邻接矩阵来表示一组较小矩阵中的图形。 如果没有这种技术,我将不得不以一种可能容易出错或令人沮丧的方式迭代组件。 例如,我可能不得不执行each_with_index 相反,我将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]]

如果新数据可以是数组或标量,并且您想防止新数据被嵌套(如果它是数组),那么 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 
a = ['a', 'b']
b = ['c', 'd']
arr = [a, b].flatten

这不会删除重复项,但是

a|b

删除重复项。

我很惊讶没有人提到过reduce ,当您有一组数组时,它运行良好:

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

somearray = [“一些”,“东西”]

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

一些数组 + 另一个数组

我发现推送或附加数组然后将它们展平到位更容易,如下所示:

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