Как вы добавляете массив в другой массив в Ruby и не получаете многомерный результат?

somearray = ["some", "thing"]

anotherarray = ["another", "thing"]

somearray.push(anotherarray.flatten!)

Я ожидал

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

Ответ 1

У вас есть работоспособная идея, но #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

Ответ 2

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

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

Ответ 3

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

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

CONCAT (other_ary)

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

Итак,

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

Ответ 4

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

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

array3 = array1|array2

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

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

Ответ 5

Легкий метод, который работает с версией 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]

Ответ 6

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

Ответ 7

(array1 + array2).uniq

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

Ответ 8

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

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

a.push(*b)

или

a += b

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

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

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

Ответ 9

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

Ответ 10

Вопрос, по сути, заключается в том, как "объединить массивы в Ruby". Естественно, ответ заключается в использовании concat или + как упоминалось почти в каждом ответе.

Естественным продолжением вопроса будет "как выполнить последовательную конкатенацию 2D-массивов в Ruby". Когда я googled "ruby concatenate matrices", этот SO-вопрос был лучшим результатом, поэтому я подумал, что оставлю свой ответ на этот (непомеченный, но связанный) вопрос здесь для потомков.


В некоторых приложениях вы можете "объединить" два 2D-массива по-разному. Что-то вроде,

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

Это что-то вроде "увеличения" матрицы. Например, я использовал этот метод для создания единственной матрицы смежности для представления графика из группы меньших матриц. Без этой техники мне пришлось бы перебирать компоненты таким образом, чтобы можно было подумать об ошибках или разочарованиях. Например, мне, возможно, пришлось бы делать each_with_index. Вместо этого я объединил zip и сплющил следующим образом,

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

Ответ 11

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

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

Ответ 12

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

Ответ 13

Если новые данные могут быть массивом или скаляром, и вы хотите, чтобы новые данные были вложенными, если они были массивом, оператор 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 

Ответ 14

Я удивлен, что никто не упомянул reduce, который хорошо работает, когда у вас есть массив массивов:

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

Ответ 15

a = ['a', 'b']
b = ['c', 'd']
arr = [a, b].flatten

Это не приведет к удалению дубликатов, но

a|b

удаляет дубликаты.

Ответ 16

Мне легче нажимать или добавлять массивы, а затем сглаживать их на месте, например:

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

Ответ 17

somearray = ["some", "thing"]

anotherarray = ["другой", "вещь"]

Somearray + Anotherarray