somearray = ["some", "thing"]
anotherarray = ["another", "thing"]
somearray.push(anotherarray.flatten!)
Я ожидал
["some","thing","another","thing"]
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):
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.
Попробуйте это, он объединит ваши массивы, удаляя дубликаты
array1 = ["foo", "bar"]
array2 = ["foo1", "bar1"]
array3 = array1|array2
http://www.ruby-doc.org/core/classes/Array.html
В дополнительной документации смотрите "Set Union"
Легкий метод, который работает с версией 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]
Вот два способа, обратите внимание, что в этом случае первый способ назначает новый массив (переводится как 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"]
(array1 + array2).uniq
Таким образом вы сначала получаете элементы массива. Вы не получите дубликатов.
a = ["some", "thing"]
b = ["another", "thing"]
Чтобы добавить b
в a
и сохранить результат в a
:
a.push(*b)
или
a += b
В любом случае a
становится:
["some", "thing", "another", "thing"]
но в первом случае элементы b
добавляются к существующему массиву a
, а во втором случае два массива объединяются вместе, и результат сохраняется в a
.
В ответ на @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)
когда массивы достаточно велики.
Вопрос, по сути, заключается в том, как "объединить массивы в 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]]
Это еще один способ сделать это.
[somearray, anotherarray].flatten
=> ["some", "thing", "another", "thing"]
["some", "thing"] + ["another" + "thing"]
Если новые данные могут быть массивом или скаляром, и вы хотите, чтобы новые данные были вложенными, если они были массивом, оператор 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
Я удивлен, что никто не упомянул reduce
, который хорошо работает, когда у вас есть массив массивов:
lists = [["a", "b"], ["c", "d"]]
flatlist = lists.reduce(:+) # ["a", "b", "c", "d"]
a = ['a', 'b']
b = ['c', 'd']
arr = [a, b].flatten
Это не приведет к удалению дубликатов, но
a|b
удаляет дубликаты.
Мне легче нажимать или добавлять массивы, а затем сглаживать их на месте, например:
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 = ["другой", "вещь"]
Somearray + Anotherarray