Forum: Ruby Repacking an array of arrays

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
C1b142946c8f689ed252d0bef2d39bba?d=identicon&s=25 Kaps Lok (kapslok)
on 2007-07-10 05:00
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.
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2007-07-10 05:12
(Received via mailing list)
Hi --

On Tue, 10 Jul 2007, Kaps Lok wrote:

>
> 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
C1b142946c8f689ed252d0bef2d39bba?d=identicon&s=25 Kaps Lok (kapslok)
on 2007-07-10 06:14
unknown wrote:
> If you have ActiveSupport you can do:
>
>    array.flatten.in_groups_of(3)
>
> David

Thanks again David.
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2007-07-10 10:17
(Received via mailing list)
2007/7/10, Kaps Lok <jocubeit@gmail.com>:
>
> 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
7b4707f974af261f71943e1f2046c9ee?d=identicon&s=25 SonOfLilit (Guest)
on 2007-07-10 10:58
(Received via mailing list)
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
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2007-07-10 11:46
(Received via mailing list)
2007/7/10, SonOfLilit <sonoflilit@gmail.com>:
> 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!

> >
> > 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
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2007-07-10 14:32
(Received via mailing list)
Hi --

On Tue, 10 Jul 2007, Robert Klemme wrote:

>> 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
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2007-07-10 14:47
(Received via mailing list)
On Jul 10, 2007, at 7:26 AM, dblack@wobblini.net wrote:

>>> arrays
>
> 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 …_with_index iterators will be pretty common too:

   enum.each_with_index.inject…


James Edward Gray II
7b4707f974af261f71943e1f2046c9ee?d=identicon&s=25 SonOfLilit (Guest)
on 2007-07-10 15:17
(Received via mailing list)
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
C1b142946c8f689ed252d0bef2d39bba?d=identicon&s=25 Kaps Lok (kapslok)
on 2007-07-11 00:39
Robert Klemme wrote:
> 2007/7/10, Kaps Lok <jocubeit@gmail.com>:
>>
>> 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.
Bc8e3e2f7acb3a7d93c10e235dc0b4e1?d=identicon&s=25 yermej@gmail.com (Guest)
on 2007-07-11 15:46
(Received via mailing list)
On Jul 9, 10:00 pm, Kaps Lok <jocub...@gmail.com> wrote:
>
> 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
851acbab08553d1f7aa3eecad17f6aa9?d=identicon&s=25 Ken Bloom (Guest)
on 2007-07-11 15:51
(Received via mailing list)
On Tue, 10 Jul 2007 12:00:47 +0900, Kaps Lok wrote:

>
> 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]]
851acbab08553d1f7aa3eecad17f6aa9?d=identicon&s=25 Ken Bloom (Guest)
on 2007-07-11 15:53
(Received via mailing list)
On Tue, 10 Jul 2007 17:57:40 +0900, SonOfLilit wrote:

> a = [[1, 4, 7, 10, 13], [2, 5, 8, 11, 14], [3, 6, 9, 12, 15]]
>
> a0 = a.shift
>
> p a0.zip(*a)

In that case, you'd just use a.transpose
This topic is locked and can not be replied to.