Если я хочу чередовать набор массивов в Ruby, и каждый массив был такой же длины, мы могли бы сделать так:
a.zip(b).zip(c).flatten
Однако, как мы можем решить эту проблему, если массивы могут быть разных размеров?
Мы могли бы сделать что-то вроде:
def interleave(*args)
raise 'No arrays to interleave' if args.empty?
max_length = args.inject(0) { |length, elem| length = [length, elem.length].max }
output = Array.new
for i in 0...max_length
args.each { |elem|
output << elem[i] if i < elem.length
}
end
return output
end
Но есть ли лучший 'Ruby 'способ, возможно, используя zip или transpose или что-то подобное?
Если в исходных массивах нет nil
, вам нужно только расширить первый массив nil
s, zip автоматически дополнит остальные с ноль
. Это также означает, что вы можете использовать compact
для очистки от лишних записей, что, надеюсь, более эффективно, чем явные циклы.
def interleave(a,*args)
max_length = args.map(&:size).max
padding = [nil]*[max_length-a.size, 0].max
(a+padding).zip(*args).flatten.compact
end
Вот немного более сложная версия, которая работает, если массивы do содержат ноль
def interleave(*args)
max_length = args.map(&:size).max
pad = Object.new()
args = args.map{|a| a.dup.fill(pad,(a.size...max_length))}
([pad]*max_length).zip(*args).flatten-[pad]
end