Объединение и перемежение двух массивов в Ruby

У меня есть следующий код:

a = ["Cat", "Dog", "Mouse"]
s = ["and", "&"]

Я хочу объединить массив s в массив a, который дал бы мне:

["Cat", "and", "Dog", "&", "Mouse"]

Просматривая Ruby Array и Enumerable docs, я не вижу такого метода, который выполнит это.

Есть ли способ, которым я могу это сделать без итерации через каждый массив?

Ответ 1

Вы можете сделать это с помощью

a.zip(s).flatten.compact

Ответ 2

Это не даст массив результатов в порядке, на который попросил Крис, но если порядок полученного массива не имеет значения, вы можете просто использовать a |= b. Если вы не хотите мутировать a, вы можете написать a | b и присвоить результат переменной.

См. документацию объединения соединений для класса Array в http://www.ruby-doc.org/core/classes/Array.html#M000275.

В этом ответе предполагается, что вы не хотите дублировать элементы массива. Если вы хотите разрешить дублирование элементов в вашем конечном массиве, a += b должен сделать трюк. Опять же, если вы не хотите мутировать a, используйте a + b и присвойте результат переменной.

В ответ на некоторые комментарии на этой странице эти два решения будут работать с массивами любого размера.

Ответ 3

Если вы не хотите дублировать, почему бы просто не использовать оператор union:

new_array = a | s

Ответ 4

s.inject(a, :<<)

s   #=> ["and", "&"]
a   #=> ["Cat", "Dog", "Mouse", "and", "&"]

Это не дает вам заказ, который вы просили, но это хороший способ слияния двух массивов, добавляя их.

Ответ 5

Здесь предлагается решение, позволяющее чередовать несколько массивов разных размеров (общее решение):

arr = [["Cat", "Dog", "Mouse", "boo", "zoo"],
 ["and", "&"],
 ["hello", "there", "you"]]

first, *rest = *arr; first.zip(*rest).flatten.compact
=> ["Cat", "and", "hello", "Dog", "&", "there", "Mouse", "you", "boo", "zoo"]

Ответ 6

Это не совсем элегантный, но он работает для массивов любого размера:

>> a.map.with_index { |x, i| [x, i == a.size - 2 ? s.last : s.first] }.flatten[0..-2] 
#=> ["Cat", "and", "Dog", "&", "Mouse"]

Ответ 7

Как насчет более общего решения, которое работает, даже если первый массив не является самым длинным и принимает любое количество массивов?

a = [
    ["and", "&"],
    ["Cat", "Dog", "Mouse"]
]

b = a.max_by(&:length)
a -= [b]
b.zip(*a).flatten.compact

 => ["Cat", "and", "Dog", "&", "Mouse"]

Ответ 8

Один из способов чередования, а также гарантии того, какой массив является самым большим для метода zip, состоит в том, чтобы заполнить один из массивов nil до другого размера массива. Таким образом, вы также гарантируете, какой элемент какого массива будет на первой позиции:

preferred_arr = ["Cat", "Dog", "Mouse"]
other_arr = ["and","&","are","great","friends"]

preferred_arr << nil while preferred_arr.length < other_arr.length
preferred_arr.zip(other_arr).flatten.compact
#=> ["Cat", "and", "Dog", "&", "Mouse", "are", "great", "friends"]

Ответ 9

Чтобы справиться с ситуацией, когда оба a & s не одного размера:

a.zip(s).flatten.compact | s
  • .compact удалит nil, когда a больше, чем s
  • | s добавит оставшиеся элементы из s, когда a меньше, чем s

Ответ 10

arr = [0, 1]
arr + [2, 3, 4]

//outputs [0, 1, 2, 3, 4]