Array handling advice

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.

irb(main):001:0> a = [1,2,3,4,5,6,7,8,9]
=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
irb(main):002:0> b = [, , ]
=> [, , ]
irb(main):003:0> a.inject(0){|bucket, item| b[bucket] << item; bucket < 2 ?
bucket + 1 : 0}
=> 0
irb(main):004:0> b
=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
irb(main):005:0>

Though I don't know if that would be considered elegant.

HTH,

FElix

···

-----Original Message-----
From: Chris McMahon [mailto:christopher.mcmahon@gmail.com]
Sent: Friday, September 07, 2007 10:40 AM
To: ruby-talk ML
Subject: array handling advice

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.

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

···

On 9/7/07, Chris McMahon <christopher.mcmahon@gmail.com> 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']

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

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) ) }

···

On Sep 7, 12:38 pm, Chris McMahon <christopher.mcma...@gmail.com> 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.

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

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

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

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

···

On 07.09.2007 20:15, Gordon Thiesfeld wrote:

On 9/7/07, Chris McMahon <christopher.mcmahon@gmail.com> 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 }

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

···

On Sep 7, 3:32 pm, Erik Veenstra <erikv...@gmail.com> 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

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

# irb(main):002:0> b = [[], [], []]
# => [[], [], []]
# irb(main):003:0> a.inject(0){|bucket, item| b[bucket] <<
# item; bucket < 2 ? bucket + 1 : 0}
# => 0
# irb(main):004:0> b
# => [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

···

From: Felix Windt [mailto:fwmailinglists@gmail.com]
#
# 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
=>[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

kind regards -botp

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