Elegant solution for inverting zip?

Hi folks,

I came across something I thought should have an obvious answer and
came up blank. I'm hoping folks could give me a nice solution to this
problem.

Given the output below:

a = [1,2,3,4].zip([5,6,7,8])

=> [[1, 5], [2, 6], [3, 7], [4, 8]]

I'd like to recover the original two arrays, something like

unzip(a) #=> [[1,2,3,4],[5,6,7,8]]

The best ordinary solution I could come up with was this:

b = a.each_with_object([,]) do |pair, memo|
  memo[0] << pair[0]
  memo[1] << pair[1]
end

Shorter, but perhaps weirder, is:

require "matrix"
b = Matrix[*a].column_vectors.map(&:to_a)

Although either of these solutions are likely good enough for my
needs, neither feel natural to me. Anyone have something better?

-greg

Hi --

···

On Tue, 14 Jul 2009, Gregory Brown wrote:

Hi folks,

I came across something I thought should have an obvious answer and
came up blank. I'm hoping folks could give me a nice solution to this
problem.

Given the output below:

a = [1,2,3,4].zip([5,6,7,8])

=> [[1, 5], [2, 6], [3, 7], [4, 8]]

I'd like to recover the original two arrays, something like

unzip(a) #=> [[1,2,3,4],[5,6,7,8]]

a.transpose, n'est-ce pas?

David

--
David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Now available: The Well-Grounded Rubyist (http://manning.com/black2\)
Training! Intro to Ruby, with Black & Kastner, September 14-17
(More info: http://rubyurl.com/vmzN\)

*facepalm* Array#transpose is what I needed, I can't believe I forgot
that. Thanks goes to David Black via IM.

-greg

···

On Tue, Jul 14, 2009 at 9:27 AM, Gregory Brown<gregory.t.brown@gmail.com> wrote:

require "matrix"
b = Matrix[*a].column_vectors.map(&:to_a)

Gregory Brown wrote:

require "matrix"
b = Matrix[*a].column_vectors.map(&:to_a)

*facepalm* Array#transpose is what I needed, I can't believe I forgot
that. Thanks goes to David Black via IM.

That's funny - I was just trying to do more or less the same thing the
other day. Given an array of [k,v] pairs, I needed to turn it into an
array of k's and an array of v's.

I searched for a built-in method to do this, couldn't find it, so went
for the obvious solution:

    ks = src.collect { |k,v| k }
    vs = src.collect { |k,v| v }

But now I know a better way:

    ks, vs = src.transpose

Thanks for sharing!

···

On Tue, Jul 14, 2009 at 9:27 AM, Gregory > Brown<gregory.t.brown@gmail.com> wrote:

--
Posted via http://www.ruby-forum.com/\.