This project is archived and is in readonly mode.

#579 ✓resolved
Adrian Mugnolo

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

Reported by Adrian Mugnolo | July 10th, 2008 @ 07:52 AM | in 2.x

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

Comments and changes to this ticket

  • Pratik

    Pratik July 10th, 2008 @ 01:13 AM

    • 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.

  • Adrian Mugnolo

    Adrian Mugnolo July 10th, 2008 @ 02:07 AM

    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.

  • Adrian Mugnolo

    Adrian Mugnolo July 10th, 2008 @ 02:42 AM

    Fixed a bug in test_in_groups_returned_array_size.

  • RSL

    RSL July 10th, 2008 @ 03:12 AM

    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. :)

  • RSL

    RSL July 10th, 2008 @ 03:13 AM

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

  • Pratik

    Pratik July 10th, 2008 @ 03:13 AM

    • State changed from “wontfix” to “open”
  • Adrian Mugnolo

    Adrian Mugnolo July 10th, 2008 @ 06:44 AM

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

  • Tarmo Tänav

    Tarmo Tänav July 10th, 2008 @ 09:03 AM

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

  • Adrian Mugnolo

    Adrian Mugnolo July 15th, 2008 @ 05:22 AM

    Summarized both commits as one.

  • Repository

    Repository July 15th, 2008 @ 03:05 PM

    • 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...

  • Ryan Bigg

    Ryan Bigg October 9th, 2010 @ 10:03 PM

    • Tag cleared.
    • Importance changed from “” to “Low”

    Automatic cleanup of spam.

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

Attachments

Pages