Я хотел бы сделать что-то вроде join
с Array
, но вместо того, чтобы получить результат как String
, я бы хотел получить Array
. Я назову это interpolate
. Например, учитывая:
a = [1, 2, 3, 4, 5]
Я ожидаю:
a.interpolate(0) # => [1, 0, 2, 0, 3, 0, 4, 0, 5]
a.interpolate{Array.new} # => [1, [], 2, [], 3, [], 4, [], 5]
Каков наилучший способ получить это? Причина, по которой мне нужен блок, состоит в том, что когда я использую его с блоком, я хочу разные экземпляры для каждого интерполятора, который находится между ними.
Получив отличные ответы от многих, я придумал несколько модифицированных.
Это модификация ответа токланда. Я заставил это принять nil
для conj1
. А также переместил условие if conj2
за пределы цикла flat_map
, чтобы ускорить его.
class Array
def interpolate conj1 = nil, &conj2
return [] if empty?
if conj2 then first(length - 1).flat_map{|e| [e, conj2.call]}
else first(length - 1).flat_map{|e| [e, conj1]}
end << last
end
end
Это модификация ответа Виктора Мороза. Я добавил функциональность, чтобы принять блок.
class Array
def interpolate conj1 = nil, &conj2
return [] if empty?
first, *rest = self
if conj2 then rest.inject([first]) {|a, e| a.push(conj2.call, e)}
else rest.inject([first]) {|a, e| a.push(conj1, e)}
end
end
end
После теста производительности второй выглядит быстрее. Кажется, что flat_map
, хотя выглядит красиво, медленно.