Discussion in 'Ruby' started by Chris McMahon, Sep 7, 2007.

1. ### Chris McMahonGuest

There is probably a simple way to do this, but I'm drawing a blank:

I have an arbitrarily large input array, like

input = ['a','b','c','d','e','f','g']

and three target arrays like

targ_one = []
targ_two = []
targ_three = []

I want to deal out the elements of this array into three target arrays
so they end up like

['a','d','g']
['b','e']
['c','f']

It seems there should be an elegant way to do this, but I haven't hit
on it. Suggestions would be welcome.

Chris McMahon, Sep 7, 2007

2. ### Gordon ThiesfeldGuest

On 9/7/07, Chris McMahon <> wrote:
>
> There is probably a simple way to do this, but I'm drawing a blank:
>
> I have an arbitrarily large input array, like
>
> input = ['a','b','c','d','e','f','g']
>
> and three target arrays like
>
> targ_one = []
> targ_two = []
> targ_three = []
>
> I want to deal out the elements of this array into three target arrays
> so they end up like
>
> ['a','d','g']
> ['b','e']
> ['c','f']
>

This is the best I could come up with:

require 'enumerator'

input = ['a','b','c','d','e','f','g']
input = *input.enum_slice(3)
targ_one, targ_two, targ_three = input.shift.zip(*input).map{|i| i.compact }

hth

Gordon

Gordon Thiesfeld, Sep 7, 2007

3. ### AxelGuest

> There is probably a simple way to do this

Like this?:

input = ['a','b','c','d','e','f','g']
targ_one, targ_two, targ_three = input[0,3], input[3,2], input[5,2]

- Axel

Axel, Sep 7, 2007
4. ### Robert KlemmeGuest

On 07.09.2007 20:15, Gordon Thiesfeld wrote:
> On 9/7/07, Chris McMahon <> wrote:
>> There is probably a simple way to do this, but I'm drawing a blank:
>>
>> I have an arbitrarily large input array, like
>>
>> input = ['a','b','c','d','e','f','g']
>>
>> and three target arrays like
>>
>> targ_one = []
>> targ_two = []
>> targ_three = []
>>
>> I want to deal out the elements of this array into three target arrays
>> so they end up like
>>
>> ['a','d','g']
>> ['b','e']
>> ['c','f']
>>

>
> This is the best I could come up with:
>
> require 'enumerator'
>
> input = ['a','b','c','d','e','f','g']
> input = *input.enum_slice(3)
> targ_one, targ_two, targ_three = input.shift.zip(*input).map{|i| i.compact }

Cute! Here's my attempt:

\$ irb -r enumerator
irb(main):001:0> a=%w{a b c d e f g h}
=> ["a", "b", "c", "d", "e", "f", "g", "h"]
irb(main):002:0> a.to_enumeach_with_index).inject([[],[],[]])
{|ar,(x,i)| ar[i%ar.size] << x;ar}
=> [["a", "d", "g"], ["b", "e", "h"], ["c", "f"]]

Kind regards

robert

Robert Klemme, Sep 7, 2007
5. ### AxelGuest

My second attempt:

input = ['a','b','c','d','e','f','g']
targ = { 0 => targ_one=[], 1 => targ_two=[], 2 => targ_three=[] }

input.each_with_index do |elem, idx|
ii = idx.divmod(3)[1]
targ[ii] << elem
end

- Axel

Axel, Sep 7, 2007
6. ### William JamesGuest

On Sep 7, 12:38 pm, Chris McMahon <>
wrote:
> There is probably a simple way to do this, but I'm drawing a blank:
>
> I have an arbitrarily large input array, like
>
> input = ['a','b','c','d','e','f','g']
>
> and three target arrays like
>
> targ_one = []
> targ_two = []
> targ_three = []
>
> I want to deal out the elements of this array into three target arrays
> so they end up like
>
> ['a','d','g']
> ['b','e']
> ['c','f']
>
> It seems there should be an elegant way to do this, but I haven't hit
> on it. Suggestions would be welcome.

input = ['a','b','c','d','e','f','g']
def seq lo,hi,gap
(0 .. ((hi-lo)/gap)).map{|n| n*gap + lo}
end

output = (0..2).map{|i|
input.values_at( *seq(i,input.size-1,3) ) }

William James, Sep 7, 2007
7. ### Erik VeenstraGuest

For better readability, define it in a library. And if it's
defined in a library, well, you might want to write the
implementation in a readable way... :}

gegroet,
Erik V. - http://www.erikveen.dds.nl/

----------------------------------------------------------------

module Enumerable
def group_by_size(size)
res = []

each_with_index do |o, n|
res << [] if n%size == 0

res[-1] << o
end

res
end
end

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b = a.group_by_size(3)

p a
p b

----------------------------------------------------------------

Erik Veenstra, Sep 7, 2007
8. ### William JamesGuest

On Sep 7, 3:32 pm, Erik Veenstra <> wrote:
> For better readability, define it in a library. And if it's
> defined in a library, well, you might want to write the
> implementation in a readable way... :}
>
> gegroet,
> Erik V. -http://www.erikveen.dds.nl/
>
> ----------------------------------------------------------------
>
> module Enumerable
> def group_by_size(size)
> res = []
>
> each_with_index do |o, n|
> res << [] if n%size == 0
>
> res[-1] << o
> end
>
> res
> end
> end
>
> a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
> b = a.group_by_size(3)
>
> p a
> p b
>
> ----------------------------------------------------------------

1. Doesn't enum_slice do this?
2. This isn't what the o.p. wants.

William James, Sep 7, 2007
9. ### Simon KrögerGuest

Chris McMahon schrieb:
> There is probably a simple way to do this, but I'm drawing a blank:

Well, no, not exactly simple.

first, *rest = *input.enum_slice(3)
one, two, three = first.zip(*rest).map{|a| a.compact}

is the most elegant way i came up with - if you can live with a result like

["a", "d", "g"]
["b", "e", nil]
["c", "f", nil]

than you can strip it down to

first, *rest = *input.enum_slice(3)
one, two, three = first.zip(*rest)

which starts to look nice - if on the other hand you have nil values in your
data (and want to keep them) you are pretty screwed with this appoach.

cheers

Simon

Simon Kröger, Sep 7, 2007
10. ### Pena, BotpGuest

From: Felix Windt [mailto:]=20
# irb(main):002:0> b =3D [[], [], []]
# =3D> [[], [], []]
# irb(main):003:0> a.inject(0){|bucket, item| b[bucket] <<=20
# item; bucket < 2 ? bucket + 1 : 0}
# =3D> 0
# irb(main):004:0> b
# =3D> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
#=20
# Though I don't know if that would be considered elegant.

i would consider that as simple and elegant.

btw, in 1.9 there will be group_by and a with_index,
so hopefully,

a.group_by.with_index{|_,i| i%3}.values
=3D>[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

kind regards -botp

Pena, Botp, Sep 8, 2007