HiveBrain v1.2.0
Get Started
← Back to all entries
patternrubyMinor

Alternately taking elements from an array

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
elementsarrayalternatelyfromtaking

Problem

Given the task of having to return an array that alternately takes elements from two arrays, what would be most Ruby way of completing the task? As of now, I have this code, but it doesn't feel very elegant.

def alternateTake (a, b)
  raise ArgumentError, "Unequal length" if a.length != b.length
  build = []
  (0..a.length-1).each do |x|
    build << (x.even? ? a[x] : b[x])
  end
  build
end


Example input & output:

method([1, 4, 3, 7], [1, 4, 2, 33]) = [1, 4, 3, 33]
method([98, 12, 41], [35, 22, 14]) = [98, 22, 41]
method([12, 33], [66, 45, 3]) = ERROR

Solution

This one-liner should be what you're looking for:

def alternate_take(xs, ys) 
  raise ArgumentError, "Unequal length" if xs.length != ys.length
  xs.zip(ys).map.with_index{|(x,y),i| i.even? ? x : y} 
end


Follow Up

Tokland's answer to OP's followup about a solution without indexes is really clever. Here's another variation, which I don't like as much as the index version, but it answers the question:

def alternate_take(xs, ys) 
  raise ArgumentError, "Unequal length" if xs.length != ys.length
  xs.zip(ys).reduce([]){|m,(x,y)| m + (m.size.even? ? [x] : [y])} 
end

Code Snippets

def alternate_take(xs, ys) 
  raise ArgumentError, "Unequal length" if xs.length != ys.length
  xs.zip(ys).map.with_index{|(x,y),i| i.even? ? x : y} 
end
def alternate_take(xs, ys) 
  raise ArgumentError, "Unequal length" if xs.length != ys.length
  xs.zip(ys).reduce([]){|m,(x,y)| m + (m.size.even? ? [x] : [y])} 
end

Context

StackExchange Code Review Q#128535, answer score: 5

Revisions (0)

No revisions yet.