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
1 Answer 1
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
-
\$\begingroup\$ Looks good. Some details: maybe use
unless
instead ofif
, give plural names to a and b (maybe: xs, ys) and unpack the pair|(x, y), idx|
... \$\endgroup\$tokland– tokland2016年05月16日 22:55:41 +00:00Commented May 16, 2016 at 22:55 -
\$\begingroup\$ Is there any way to use iterators or something like that and avoid using indices? \$\endgroup\$Michael– Michael2016年05月16日 22:57:12 +00:00Commented May 16, 2016 at 22:57
-
\$\begingroup\$ @tokland, Both good suggestions, edited. \$\endgroup\$Jonah– Jonah2016年05月16日 23:01:17 +00:00Commented May 16, 2016 at 23:01
-
2\$\begingroup\$ @Michael. A lot of ways, for example:
xs.zip(ys, [true, false].cycle).map { |x, y, take_x| take_x ? x : y }
. Not that there is anything wrong with using with_index. \$\endgroup\$tokland– tokland2016年05月16日 23:01:28 +00:00Commented May 16, 2016 at 23:01 -
\$\begingroup\$ Jonah, the second version is so horrible.. I don't think it's worth it. Children watching! :) There is nothing wrong with using with_index, it's not the same than accessing the array by indexes (which is indeed ugly). \$\endgroup\$tokland– tokland2016年05月17日 07:23:30 +00:00Commented May 17, 2016 at 7:23