209

I have an array

foo = %w(1 2 3 4 5 6 7 8 9 10)

How can I split or "chunk" this into smaller arrays?

class Array
  def chunk(size)
    # return array of arrays
  end
end

foo.chunk(3)
# => [[1,2,3],[4,5,6],[7,8,9],[10]]
maček
  • 76,434
  • 37
  • 167
  • 198

2 Answers2

398

Take a look at Enumerable#each_slice:

foo.each_slice(3).to_a
#=> [["1", "2", "3"], ["4", "5", "6"], ["7", "8", "9"], ["10"]]
Mladen Jablanović
  • 43,461
  • 10
  • 90
  • 113
  • 3
    So simple, so ruby. I used `t = []; d.each_slice(3) {|s| t << s}`, ... why didn't I just try #to_a, thanks man. – Dorian Aug 25 '12 at 08:12
  • Nice. I used something similar to `foo.each_slice(3).each_with_index { |f, i| puts "#{f}, #{i}" }` in order to work through the array in slices (or "chunks"). – user664833 Sep 14 '12 at 19:08
  • 1
    If array size doesn't divide evenly into the number of chunks, is there a way to merge the remainder chunk with the previous one? So in your example, `["10"]` would be merged with `["7", "8", "9"]` to make the last chunk `["7", "8", "9", "10"]`? – Mohamad Apr 11 '16 at 16:33
62

If you're using rails you can also use in_groups_of:

foo.in_groups_of(3)
tirdadc
  • 4,603
  • 3
  • 38
  • 45
Head
  • 4,691
  • 3
  • 30
  • 18
  • 16
    note that in_groups_of uses each_slice and also performs "padding" if you don't need the padding, then go with each_slice – Urkle Dec 29 '11 at 19:43
  • 8
    Actually, you can pass a second parameter to in_groups_of, telling it what to pad with, and if that is false, it doesn't pad. So, no need for each_slice either way. – FrontierPsycho May 21 '12 at 10:30
  • 5
    Be careful. It makes empty element for `nil`. For example, if you makes `arr = [0,1,2,3,4]` with `in_groups_of(3)`, then its result is `[[0,1,2],[3,4,nil]]`. In some case, it can make some troubles. – Penguin Nov 23 '15 at 11:45
  • 7
    @Penguin if you use `foo.in_groups_of(2, false)` it won't pad with `nil` elements – Canuk May 28 '16 at 19:59