Forum: Ruby on Rails Tricky ruby array grouping method

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.
A7bf258bf1119b6f386728079391bef0?d=identicon&s=25 danlunde (Guest)
on 2007-07-13 22:53
(Received via mailing list)
I want to define a method that performs the following operation:

Given an array: array = [a, b, c, d, e, f, g, h, i]
My imaginary method (let's call it nest_by) would produce these
results
array.nest_by(2)
=> [[a, b], [c, d], [d, e], [f, g], [h, i]]
array.nest_by(3)
=> [[a, b, c], [d, e, f], [g, h, i]]
array.nest_by(4)
=> [[a, b, c, d], [e, f, g, h], [i, nil, nil, nil]]

The contents of the array can be anything (including array's
themselves).
This is sort of like the rails Array.in_groups_of(n), but uses the
array.size to determine the number of elements in each new nested
array.

Any thoughts?

Daniel
A7bf258bf1119b6f386728079391bef0?d=identicon&s=25 danlunde (Guest)
on 2007-07-14 00:00
(Received via mailing list)
Ack, what I explained WAS array.in_groups_of(n).

What I'm ACTUALLY looking for is:
array.nest_by(2)
=> [[a, b, c, d, e], [f, g, h, i]]
array.nest_by(3)
=> [[a, b, c], [d, e, f], [g, h, i]]
array.nest_by(4)
=> [[a, b, c], [d, e], [f, g], [h, i]]

Where nest_by(n) produces n nested arrays.  In the case of 2 and 4
when it's not an balanced match, distribute the extras amongst first
arrays.
C237cf537a06b60921c97804679e3b15?d=identicon&s=25 John Barnette (Guest)
on 2007-07-14 02:00
(Received via mailing list)
On 7/13/07, danlunde <danlunde@gmail.com> wrote:
> arrays.
This is probably better posted in ruby-talk. Here's a stab, though:

class Array
  def nest_by(group_count)
    in_groups_of(size / group_count + size %
group_count).collect(&:compact)
  end
end


~ j.
9dfe8c734b0f9b37a4e218425c0a2138?d=identicon&s=25 gene.tani@gmail.com (Guest)
on 2007-07-14 07:31
(Received via mailing list)
On Jul 13, 2:59 pm, danlunde <danlu...@gmail.com> wrote:
> Ack, what I explained WAS array.in_groups_of(n).
>
> What I'm ACTUALLY looking for is:
> array.nest_by(2)
> => [[a, b, c, d, e], [f, g, h, i]]
> array.nest_by(3)
> => [[a, b, c], [d, e, f], [g, h, i]]
> array.nest_by(4)
> => [[a, b, c], [d, e], [f, g], [h, i]]
>

you could probably golf this, but:

require 'enumerator'
class Array
    def nest_by(length_of_out)
        num_per_element, remainder =
self.length.divmod(length_of_out);
        temp=[]
        self.reverse.each_slice(num_per_element) {  |slice| temp <<
slice}
        if remainder>0
            temp[-2]+= temp[-1]
            temp.slice!(-1)
        end
        return temp.reverse
    end
end
A7bf258bf1119b6f386728079391bef0?d=identicon&s=25 danlunde (Guest)
on 2007-07-16 22:09
(Received via mailing list)
Thanks gene.tani, you got me close enough.  The only problem with your
solution was that if there were 2 remaining elements, I wanted those
distributed among the first two nested array, not all in the first
array.  Here's the finished solution for what I was looking for:

class Array
  def in_n_groups(n)
    num_per_element, remainder = self.length.divmod(n);
    orig = self.dup
    temp = []
    until orig.empty?
      if remainder > 0
        temp << orig.slice!(0, num_per_element+1)
        remainder -= 1
      else
        temp << orig.slice!(0, num_per_element)
      end
    end
    return temp
  end
end

array = %w{ a b c d e f g h i j k }
array
=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"]

array.in_n_groups(2)
=> [["a", "b", "c", "d", "e", "f"], ["g", "h", "i", "j", "k"]]

array.in_n_groups(3)
=> [["a", "b", "c", "d"], ["e", "f", "g", "h"], ["i", "j", "k"]]

array.in_n_groups(4)
=> [["a", "b", "c"], ["d", "e", "f"], ["g", "h", "i"], ["j", "k"]]

Great for distributing long lists of data between balanced table
columns.  Especially when you only want n columns.

Thanks everyone for helping.

Daniel
This topic is locked and can not be replied to.