opensoul.org

Splitting Hairs and Arrays

June 19, 2008 code 4 min read

Am I just dumb, or is it really a lot harder than it should be to break an array up into a set number of chunks?

For example, I have a list of 8 items that I want to break into 3 arrays, each displayed in their own unordered list, like this:

  • Item 1
  • Item 2
  • Item 3
  • Item 4
  • Item 5
  • Item 6
  • Item 7
  • Item 8

Brian and I spent a ridiculous amount of time (20 minutes, at least) trying to come up with a clean solution to this seemingly simple problem. The closest thing there is to a solution is Enumerable#each_slice in Ruby core or Array#in_groups_of in Active Support.

<% my_array.each_slice((my_array.size.to_f / 3).ceil) do |list| %>
  <ul>
    <% list.each do |item| %>
      <li><%= item %></li>
    <% end %>
  </ul>
<% end %>

or

<% my_array.in_groups_of((my_array.size.to_f / 3).ceil, false) do |list| %>
  <ul>
    <% list.each do |item| %>
      <li><%= item %></li>
    <% end %>
  </ul>
<% end %>

There’s not really a difference between either solution. Both requires that we calculate how many items we want in each list. (We convert the size to a float, divide by the number of columns, then round up. This gives us the same number of items in each column, with the last column having fewer.)

Our solution

We didn’t like having that much logic in the view, so we added a method to enumerable; we thought the division (/) method seemed appropriate since we’re dividing the array into equal parts.

module Enumerable
  # Divide into groups
  def /(num)
    returning [] do |result|
      each_slice((size.to_f / num).ceil) {|a| result << a }
    end
  end
end

Note: this method is now in our awesomeness plugin.

So now we can just divide our array into chunks in the view.

<% (my_array / 3).each do |list| %>
  <ul>
    <% list.each do |item| %>
      <li><%= item %></li>
    <% end %>
  </ul>
<% end %>

Are we dumb? Is there already a way to do this that wasn’t obvious to us and we just wasted our time (and I wasted even more time blogging about it)?

Update: Thanks to Aaron Pfeifer for pointing out the [discussion on Jay Field's blog](http://blog.jayfields.com/2007/09/ruby-arraychunk.html) about something similar. I've refactored this code in [awesomeness](http://github.com/collectiveidea/awesomeness/tree/master/lib/awesomeness/core_ext/enumerable.rb) to be more "robust' (read: convoluted).

This content is open source. Suggest Improvements.

@bkeepers

avatar of Brandon Keepers I am Brandon Keepers, and I work at GitHub on making Open Source more approachable, effective, and ubiquitous. I tend to think like an engineer, work like an artist, dream like an astronaut, love like a human, and sleep like a baby.