Repacking an array of arrays

K

Kaps Lok

Is there an elegant (maybe a one-liner) for repacking:

[[1, 4, 7, 10, 13], [2, 5, 8, 11, 14], [3, 6, 9, 12, 15]]

to?

[[1, 4, 7], [10, 13, 2], [5, 8, 11], [14, 3, 6], [9, 12, 15]]

So rather than having 3 arrays each with 5 elements, I get five arrays
of 3 elements each...

the only way I can see to do this is by looping the array, and creating
new arrays.

Any help would be much appreciated.
 
D

dblack

Hi --

Is there an elegant (maybe a one-liner) for repacking:

[[1, 4, 7, 10, 13], [2, 5, 8, 11, 14], [3, 6, 9, 12, 15]]

to?

[[1, 4, 7], [10, 13, 2], [5, 8, 11], [14, 3, 6], [9, 12, 15]]

So rather than having 3 arrays each with 5 elements, I get five arrays
of 3 elements each...

the only way I can see to do this is by looping the array, and creating
new arrays.

If you have ActiveSupport you can do:

array.flatten.in_groups_of(3)

with the caveat about flatten that it flattens greedily. If you
don't, you can easily get it or roll your own in_groups_of. (It was
one of the first things I ever wrote for myself in Ruby, though I
think I called it in_slices_of or something.)


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 
Y

yermej

Is there an elegant (maybe a one-liner) for repacking:

[[1, 4, 7, 10, 13], [2, 5, 8, 11, 14], [3, 6, 9, 12, 15]]

to?

[[1, 4, 7], [10, 13, 2], [5, 8, 11], [14, 3, 6], [9, 12, 15]]

So rather than having 3 arrays each with 5 elements, I get five arrays
of 3 elements each...

the only way I can see to do this is by looping the array, and creating
new arrays.

Any help would be much appreciated.

Is the fact that it goes from 3 of 5 to 5 of 3 significant or do you
always want to go to some number of 3 element arrays? E.g. would you
ever have an array of 4 arrays of 6 elements and want to go to an
array of 6 arrays with 4 elements each?

If it's the first case, this will work, though there may be something
more elegant:

result = []
a.flatten.each_with_index {|x, i| i % 3 == 0 ? result << [x] :
result[-1] << x}

I suppose, if you need the second case, you could do something a
little more general:

result = []
a.flatten.each_with_index {|x, i| i % a.length == 0 ? result << [x] :
result[-1] << x}

Jeremy
 
K

Ken Bloom

Is there an elegant (maybe a one-liner) for repacking:

[[1, 4, 7, 10, 13], [2, 5, 8, 11, 14], [3, 6, 9, 12, 15]]

to?

[[1, 4, 7], [10, 13, 2], [5, 8, 11], [14, 3, 6], [9, 12, 15]]

So rather than having 3 arrays each with 5 elements, I get five arrays
of 3 elements each...

the only way I can see to do this is by looping the array, and creating
new arrays.

Any help would be much appreciated.

require 'enumerator'
a=[[1, 4, 7, 10, 13], [2, 5, 8, 11, 14], [3, 6, 9, 12, 15]]
a.flatten.enum_slice(3).collect
=> [[1, 4, 7], [10, 13, 2], [5, 8, 11], [14, 3, 6], [9, 12, 15]]
 
R

Robert Klemme

2007/7/10 said:
Is there an elegant (maybe a one-liner) for repacking:

[[1, 4, 7, 10, 13], [2, 5, 8, 11, 14], [3, 6, 9, 12, 15]]

to?

[[1, 4, 7], [10, 13, 2], [5, 8, 11], [14, 3, 6], [9, 12, 15]]

So rather than having 3 arrays each with 5 elements, I get five arrays
of 3 elements each...

the only way I can see to do this is by looping the array, and creating
new arrays.

Try this:

require 'enumerator'
p [[1, 4, 7, 10, 13], [2, 5, 8, 11, 14], [3, 6, 9, 12,
15]].flatten.to_enum:)each_slice, 3).to_a

Kind regards

robert
 
S

SonOfLilit

a = [[1, 4, 7, 10, 13], [2, 5, 8, 11, 14], [3, 6, 9, 12, 15]]

a0 = a.shift

p a0.zip(*a)


to grok this, ri Array#zip
 
R

Robert Klemme

2007/7/10 said:
a = [[1, 4, 7, 10, 13], [2, 5, 8, 11, 14], [3, 6, 9, 12, 15]]

a0 = a.shift

p a0.zip(*a)

This outputs

[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15]]

Which is not what the OP wanted according to his first posting (see
quote below). Still it's a nice approach!
to grok this, ri Array#zip

Is there an elegant (maybe a one-liner) for repacking:

[[1, 4, 7, 10, 13], [2, 5, 8, 11, 14], [3, 6, 9, 12, 15]]

to?

[[1, 4, 7], [10, 13, 2], [5, 8, 11], [14, 3, 6], [9, 12, 15]]

So rather than having 3 arrays each with 5 elements, I get five arrays
of 3 elements each...

the only way I can see to do this is by looping the array, and creating
new arrays.

Any help would be much appreciated.

Kind regards

robert
 
D

dblack

Hi --

2007/7/10 said:
Is there an elegant (maybe a one-liner) for repacking:

[[1, 4, 7, 10, 13], [2, 5, 8, 11, 14], [3, 6, 9, 12, 15]]

to?

[[1, 4, 7], [10, 13, 2], [5, 8, 11], [14, 3, 6], [9, 12, 15]]

So rather than having 3 arrays each with 5 elements, I get five arrays
of 3 elements each...

the only way I can see to do this is by looping the array, and creating
new arrays.

Try this:

require 'enumerator'
p [[1, 4, 7, 10, 13], [2, 5, 8, 11, 14], [3, 6, 9, 12,
15]].flatten.to_enum:)each_slice, 3).to_a

And in 1.9 I guess it would be:

array.flatten.each_slice(3).to_a

I'd like to see a method (I don't think there is one) in 1.9 that
would return the sliced-up array without the need for the explict to_a
operation. I suspect the most common use will be exactly that.


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 
J

James Edward Gray II

Hi --

2007/7/10 said:
Is there an elegant (maybe a one-liner) for repacking:
[[1, 4, 7, 10, 13], [2, 5, 8, 11, 14], [3, 6, 9, 12, 15]]
to?
[[1, 4, 7], [10, 13, 2], [5, 8, 11], [14, 3, 6], [9, 12, 15]]
So rather than having 3 arrays each with 5 elements, I get five =20
arrays
of 3 elements each...
the only way I can see to do this is by looping the array, and =20
creating
new arrays.

Try this:

require 'enumerator'
p [[1, 4, 7, 10, 13], [2, 5, 8, 11, 14], [3, 6, 9, 12,
15]].flatten.to_enum:)each_slice, 3).to_a

And in 1.9 I guess it would be:

array.flatten.each_slice(3).to_a

I'd like to see a method (I don't think there is one) in 1.9 that
would return the sliced-up array without the need for the explict to_a
operation. I suspect the most common use will be exactly that.

I bet rolling =85_with_index iterators will be pretty common too:

enum.each_with_index.inject=85


James Edward Gray II=
 
S

SonOfLilit

Oi...

How could I have misread so badly?

I'm sorry, I had this so cool elegant hammer and I guess I immediately
saw a nail :p


Aur

2007/7/10 said:
a = [[1, 4, 7, 10, 13], [2, 5, 8, 11, 14], [3, 6, 9, 12, 15]]

a0 = a.shift

p a0.zip(*a)

This outputs

[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15]]

Which is not what the OP wanted according to his first posting (see
quote below). Still it's a nice approach!
to grok this, ri Array#zip

Is there an elegant (maybe a one-liner) for repacking:

[[1, 4, 7, 10, 13], [2, 5, 8, 11, 14], [3, 6, 9, 12, 15]]

to?

[[1, 4, 7], [10, 13, 2], [5, 8, 11], [14, 3, 6], [9, 12, 15]]

So rather than having 3 arrays each with 5 elements, I get five arrays
of 3 elements each...

the only way I can see to do this is by looping the array, and creating
new arrays.

Any help would be much appreciated.

Kind regards

robert
 
K

Kaps Lok

Robert said:
2007/7/10 said:
the only way I can see to do this is by looping the array, and creating
new arrays.

Try this:

require 'enumerator'
p [[1, 4, 7, 10, 13], [2, 5, 8, 11, 14], [3, 6, 9, 12,
15]].flatten.to_enum:)each_slice, 3).to_a

Kind regards

robert

Thanks Robert,

That's an interesting solution using the enumerator. I'll have to add
that to the memory banks. I ended up using David's solution from
ActiveSupport. It's very elegant.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top