Как добавить массив в другой массив в Ruby и не получить многомерный результат? - PullRequest
431 голосов
/ 26 ноября 2009
somearray = ["some", "thing"]

anotherarray = ["another", "thing"]

somearray.push(anotherarray.flatten!)

Я ожидал

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

Ответы [ 16 ]

661 голосов
/ 26 ноября 2009

У вас есть работоспособная идея, но #flatten! находится не в том месте - он выравнивает свой приемник, так что вы можете использовать его, чтобы превратить [1, 2, ['foo', 'bar']] в [1,2,'foo','bar'].

Я, несомненно, забыл некоторые подходы, но вы можете объединить :

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

или prepend / append :

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
196 голосов
/ 26 ноября 2009

Вы можете просто использовать оператор +!

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 / ядро ​​/ классов / Array.html

62 голосов
/ 07 августа 2013

Самый чистый подход - использовать метод Array # concat ; он не создаст новый массив (в отличие от Array # +, который будет делать то же самое, но создаст новый массив).

Прямо из документов (http://www.ruby -doc.org / core-1.9.3 / Array.html # method-i-concat ):

CONCAT (other_ary)

Добавляет элементы other_ary к себе.

So

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

Наконец, вы можете использовать наш gem corelib (https://github.com/corlewsolutions/corelib), который добавляет полезные помощники в базовые классы Ruby. В частности, у нас есть метод Array # add_all , который автоматически сглаживает многомерные массивы перед выполнение конкат.

33 голосов
/ 05 января 2016

Простой метод, который работает с версией 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]
32 голосов
/ 26 ноября 2009

Попробуйте, это объединит ваши массивы, удалив дубликаты

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

array3 = array1|array2

http://www.ruby -doc.org / ядро ​​/ классов / Array.html

Дополнительную документацию смотрите на "Set Union"

27 голосов
/ 26 ноября 2009

Вот два способа, обратите внимание, что в этом случае первый способ назначает новый массив (переводится как 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"]
19 голосов
/ 24 июля 2015

(array1 + array2).uniq

Таким образом, вы сначала получаете элементы array1. Вы не получите дубликатов.

12 голосов
/ 11 января 2019
a = ["some", "thing"]
b = ["another", "thing"]

Чтобы добавить b к a и сохранить результат в a:

a.push(*b)

или

a += b

В любом случае a становится:

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

, но в первом случае элементы b добавляются к существующему массиву a, а во втором случае два массива объединяются вместе, и результат сохраняется в a.

8 голосов
/ 29 декабря 2017

Просто еще один способ сделать это.

[somearray, anotherarray].flatten
=> ["some", "thing", "another", "thing"]
8 голосов
/ 11 июня 2017

При разработке ответа @ 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), когда массивы достаточно велики.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...