Как вставить новый элемент между всеми элементами массива Ruby? - PullRequest
6 голосов
/ 24 февраля 2012

У меня есть массив, и я хочу вставить новый элемент между всеми элементами, например, как метод join. Например, у меня есть

[1, [], "333"]

и что мне нужно, это

[1, {}, [], {}, "333"]

Обратите внимание, что новый пустой хеш был вставлен между всеми элементами.

Edit: В настоящее время у меня есть:

irb(main):028:0> a = [1, [], "333"]
=> [1, [], "333"]
irb(main):029:0> a = a.inject([]){|x, y| x << y; x << {}; x}
=> [1, {}, [], {}, "333", {}]
irb(main):030:0> a.pop
=> {}
irb(main):031:0> a
=> [1, {}, [], {}, "333"]
irb(main):032:0>

Я хочу знать лучший способ.

Ответы [ 8 ]

14 голосов
/ 24 февраля 2012
[1, 2, 3].flat_map { |x| [x, :a] }[0...-1]
#=> [1, :a, 2, :a, 3]

К вашему сведению, эта функция называется intersperse (по крайней мере, в Haskell).

[Обновить] Если вы хотите избежать среза (который создал копию массива):

[1, 2, 3].flat_map { |x| [x, :a] }.tap(&:pop)
#=> [1, :a, 2, :a, 3]
2 голосов
/ 23 января 2013

Другое похожее решение использует #product:

[1, 2, 3].product([{}]).flatten(1)[0...-1]
# => [ 1, {}, 2, {}, 3 ]
1 голос
/ 01 декабря 2016

Один из подходов - заархивировать другой массив нужных элементов, а затем сгладить его с помощью depth = 1:

> arr = [1, [], "333"]
> element = {}
> interspersed = arr.zip([element] * (arr.size - 1)).flatten(1).compact
> # [1, {}, [], {}, "333" ]

. Вы можете расширить Array, чтобы сделать это поведение более доступным.

например,

[43] pry (main)> [1,2,3] .intersperse ('a')
=> [1, "a", 2,"а", 3]

1 голос
/ 24 февраля 2012

Вы можете сделать что-то вроде:

a = [1, [], "333"]
new_a = a.collect {|e| [e, {}]}.flatten(1)
=> [1, {}, [], {}, "333", {}]

Вам нужно сделать .flatten(1), потому что без него выровняется ваш пустой массив.

Или, как @David Grayson говорит в комментарии, вы можете сделать flat_map, который будет делать то же самое.

a.flat_map {|e| [e, {}]}
=> [1, {}, [], {}, "333", {}]

@ tokland имеет правильный ответ, если последний {} не нужен. Вы возвращаете срез от 0 до длины - 1 или [0..-1].

1 голос
/ 24 февраля 2012
a = [1,2,3]
h, *t = a
r = [h]
t.each do |e|
  r.push({}, e)
end
r #=> [1, {}, 2, {}, 3]
0 голосов
/ 19 сентября 2017
[1, 2, 3, 4, 5].inject { |memo, el| Array(memo) << {} << el }
#=> [1, {}, 2, {}, 3, {}, 4, {}, 5]

inject будет использовать первый элемент для начала, так что вам не нужно возиться с индексами.

0 голосов
/ 24 февраля 2012

Еще один, похожий на тот, что у Токланда:

xs.inject([]){|x,y| x << y << {}}[0...-1]
0 голосов
/ 24 февраля 2012
irb(main):054:0* [1, 2, 3, 4, 5, 6, 7, 8, 9].each_slice(1).flat_map {|e| e << "XXX"}[0...-1]
=> [1, "XXX", 2, "XXX", 3, "XXX", 4, "XXX", 5, "XXX", 6, "XXX", 7, "XXX", 8, "XXX", 9]
irb(main):055:0> [1, 2, 3, 4, 5, 6, 7, 8, 9].each_slice(2).flat_map {|e| e << "XXX"}[0...-1]
=> [1, 2, "XXX", 3, 4, "XXX", 5, 6, "XXX", 7, 8, "XXX", 9]
irb(main):056:0> [1, 2, 3, 4, 5, 6, 7, 8, 9].each_slice(3).flat_map {|e| e << "XXX"}[0...-1]
=> [1, 2, 3, "XXX", 4, 5, 6, "XXX", 7, 8, 9]
irb(main):057:0> [1, 2, 3, 4, 5, 6, 7, 8, 9].each_slice(4).flat_map {|e| e << "XXX"}[0...-1]
=> [1, 2, 3, 4, "XXX", 5, 6, 7, 8, "XXX", 9]
irb(main):058:0> [1, 2, 3, 4, 5, 6, 7, 8, 9].each_slice(5).flat_map {|e| e << "XXX"}[0...-1]
=> [1, 2, 3, 4, 5, "XXX", 6, 7, 8, 9]
irb(main):059:0> [1, 2, 3, 4, 5, 6, 7, 8, 9].each_slice(6).flat_map {|e| e << "XXX"}[0...-1]
=> [1, 2, 3, 4, 5, 6, "XXX", 7, 8, 9]
irb(main):060:0> [1, 2, 3, 4, 5, 6, 7, 8, 9].each_slice(7).flat_map {|e| e << "XXX"}[0...-1]
=> [1, 2, 3, 4, 5, 6, 7, "XXX", 8, 9]
irb(main):061:0> [1, 2, 3, 4, 5, 6, 7, 8, 9].each_slice(8).flat_map {|e| e << "XXX"}[0...-1]
=> [1, 2, 3, 4, 5, 6, 7, 8, "XXX", 9]
irb(main):062:0> [1, 2, 3, 4, 5, 6, 7, 8, 9].each_slice(9).flat_map {|e| e << "XXX"}[0...-1]
=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
irb(main):063:0>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...