Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

Add in_groups to ActiveSupport::CoreExtensions::Array::Grouping

#579

This patch provides an accompanying method to in_groups_of, named in_groups.

The purpose of in_groups is to split or iterate over an array in a specified number of groups, whereas in_groups_of offers the same semantics to operate on groups of a specified size.

In other words, the existing method says "divide this into n groups of x elements each", this one says "divide this into x groups of n elements each" (where x is specified, n unknown).

Some code examples:

>> %w(1 2 3 4 5 6 7 8 9 10).in_groups_of(3)
=> [["1", "2", "3"], ["4", "5", "6"], ["7", "8", "9"], ["10", nil, nil]]
>> %w(1 2 3 4 5 6 7 8 9 10).in_groups(3)
=> [["1", "2", "3", "4"], ["5", "6", "7", nil], ["8", "9", "10", nil]]
>> %w(1 2 3 4 5 6 7 8 9 10).in_groups(3, false)
=> [["1", "2", "3", "4"], ["5", "6", "7"], ["8", "9", "10"]]

I've found myself writing this kind of code for views while trying to accomodate several items in n-column layouts:

<% @locations.in_groups(3, false) do |group| %>
  <ul style="float: left;">
    <%= render :partial => "location", :collection => group %>
  </ul>
<% end %>

Note that in_groups will always return the specified number of groups. That remains true even for edge cases like:

>> %w().in_groups(5)
=> [[], [], [], [], []]
>> %w(1).in_groups(5)
=> [["1"], [nil], [nil], [nil], [nil]]
>> %w(1 2 3 4 5).in_groups(5)
=> [["1"], ["2"], ["3"], ["4"], ["5"]]
>> %w(1 2 3 4 5 6).in_groups(5)
=> [["1", "2"], ["3", nil], ["4", nil], ["5", nil], ["6", nil]]

(Thanks to RSL for improving the wording and original examples.)

Reported by Adrian Mugnolo · July 10th, 2008 @ 07:52 AM

State: resolved
Milestone: 2.x
Assigned to: nobody
Importance: Low

Activity

  1. Pratik
    Pratik
    • State changed from new to wontfix

    I feel it's bit too complex. And extensions like this are a better fit for Rails.root/lib rather than in core.

    But if you disagree, please continue the discussion in rails core mailing list.

    Thanks.

    July 10th, 2008 @ 01:13 AM

  2. Adrian Mugnolo
    Adrian Mugnolo

    Pratik,

    I would gladly continue the discussion in the Rails Core mailing list. Still, let me comment on complexity and use cases.

    The method interface matches 1:1 the one for in_groups_of -- which in the scope of Rails, lays on the easy side. So use shouldn't be a problem to anyone already using in_groups_of.

    Both methods appear as a natural fit. When slicing an array you're usually concerned about either: subarray size (where you would use in_groups_of) or, number of subarrays (where you could use in_groups).

    Possible use cases are: view code for n-column layout as in "x accounts/addresses to be splitted in y elements to be floated and rendered as columns"; resource allocation as in "x conference attendees to be arranged along y available rooms"; and many others.

    July 10th, 2008 @ 02:07 AM

  3. Adrian Mugnolo
    Adrian Mugnolo

    Fixed a bug in test_in_groups_returned_array_size.

    July 10th, 2008 @ 02:42 AM

  4. RSL
    RSL

    I found the example code in the ticket a little confusing and didn't see the point. Then it clicked in my head that where the existing method says "divide this into n groups of three" this says "divide this into three groups of n". You can see this a little better in:

    1. Produces four groups of three

    >> %w(1 2 3 4 5 6 7 8 9 10).in_groups_of(3)

    => [["1", "2", "3"], ["4", "5", "6"], ["7", "8", "9"], ["10", nil, nil]]

    1. Produces three groups of four

    %w(1 2 3 4 5 6 7 8 9 10).in_groups(3)

    => [["1", "2", "3", "4"], ["5", "6", "7", nil], ["8", "9", "10", nil]]

    It seems like a natural converse method to me. :)

    July 10th, 2008 @ 03:12 AM

  5. RSL
    RSL

    Those numbers were supposed to be comments using #. Silly me forgot about formatting.

    July 10th, 2008 @ 03:13 AM

  6. Pratik
    Pratik
    • State changed from wontfix to open

    July 10th, 2008 @ 03:13 AM

  7. Adrian Mugnolo
    Adrian Mugnolo

    RSL, thanks for coming up with much better wording and code samples! :-)

    July 10th, 2008 @ 06:44 AM

  8. Tarmo Tänav
    Tarmo Tänav

    Looks useful, +1

    Though I'd like to point out that if anyone should need a columns-first order (which gives the same fill as in_groups, but the elements are first ordered by row and then column), there are two ways:

    1. Here 4 is the number of result groups

    >> %w(1 2 3 4 5 6 7 8 9 10).in_groups_of(4).transpose

    => [["1", "5", "9"], ["2", "6", "10"], ["3", "7", nil], ["4", "8", nil]]

    1. Or another way to do the same:

    >> y=%w(1 2 3 4 5 6 7 8 9 10).in_groups_of(4)

    => [["1", "2", "3", "4"], ["5", "6", "7", "8"], ["9", "10", nil, nil]]

    >> y.shift.zip(*y)

    => [["1", "5", "9"], ["2", "6", "10"], ["3", "7", nil], ["4", "8", nil]]

    July 10th, 2008 @ 09:03 AM

  9. Adrian Mugnolo
    Adrian Mugnolo

    Summarized both commits as one.

    July 15th, 2008 @ 05:22 AM

  10. Repository
    Repository
    • State changed from open to resolved

    (from [fc89a951933638b051bb1f9e1339ee6ae7c94cda]) Add in_groups to ActiveSupport::CoreExtensions::Array::Grouping. [#579 state:resolved]

    Signed-off-by: Pratik Naik

    http://github.com/rails/rails/co...

    July 15th, 2008 @ 03:05 PM

  11. Ryan Bigg
    Ryan Bigg
    • Tag cleared.
    • Importance changed from to Low

    Automatic cleanup of spam.

    October 9th, 2010 @ 10:03 PM