array handling advice

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

  1. 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
    #1
    1. Advertising

  2. 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
    #2
    1. Advertising

  3. Chris McMahon

    Axel Guest


    > 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
    #3
  4. 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_enum:)each_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
    #4
  5. Chris McMahon

    Axel Guest

    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
    #5
  6. 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
    #6
  7. 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
    #7
  8. 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
    #8
  9. 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
    #9
  10. Chris McMahon

    Pena, Botp Guest

    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
    #10
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Asun Friere
    Replies:
    1
    Views:
    498
    Paul Boddie
    Aug 27, 2003
  2. Peter Hansen
    Replies:
    23
    Views:
    869
    Anton Vredegoor
    Sep 5, 2003
  3. Gerrit Holl
    Replies:
    16
    Views:
    616
    Tom Plunket
    Aug 29, 2003
  4. Asun Friere
    Replies:
    0
    Views:
    479
    Asun Friere
    Aug 28, 2003
  5. Michele Simionato
    Replies:
    2
    Views:
    385
    Jacek Generowicz
    Sep 1, 2003
Loading...

Share This Page