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.

[‘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

On 9/7/07, Chris McMahon [email protected] wrote:

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

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

On 07.09.2007 20:15, Gordon T. wrote:

targ_two = []
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

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

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

On Sep 7, 3:32 pm, Erik V. [email protected] wrote:

def group_by_size(size)
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.

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

On Sep 7, 12:38 pm, Chris McMahon [email protected]
wrote:

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

From: Felix W. [mailto:[email protected]]

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]]

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