Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to interleave arrays of different length in Ruby

Tags:

arrays

ruby

If I want to interleave a set of arrays in Ruby, and each array was the same length, we could do so as:

a.zip(b).zip(c).flatten

However, how do we solve this problem if the arrays can be different sizes?

We could do something like:

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

But is there a better 'Ruby' way, perhaps using zip or transpose or some such?

like image 219
ChrisInEdmonton Avatar asked Aug 27 '10 18:08

ChrisInEdmonton


1 Answers

Here is a simpler approach. It takes advantage of the order that you pass the arrays to zip:

def interleave(a, b)
  if a.length >= b.length
    a.zip(b)
  else
    b.zip(a).map(&:reverse)
  end.flatten.compact
end

interleave([21, 22], [31, 32, 33])
# => [21, 31, 22, 32, 33]

interleave([31, 32, 33], [21, 22])
# => [31, 21, 32, 22, 33]

interleave([], [21, 22])
# => [21, 22]

interleave([], [])
# => []

Be warned: this removes all nil's:

interleave([11], [41, 42, 43, 44, nil])
# => [11, 41, 42, 43, 44]
like image 180
David J. Avatar answered Oct 04 '22 13:10

David J.