Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Split array into smaller arrays of equal size (See related posts)

Split an array of elements into a set of smaller arrays of equal size. Extra elements are preferentially assigned to earlier arrays. If there are no elements in a given returned array it will be [] (empty array)

# use as standalone function
def chunk_array(array, pieces=2)
  len = array.length;
  mid = (len/pieces)
  chunks = []
  start = 0
  1.upto(pieces) do |i|
    last = start+mid
    last = last-1 unless len%pieces >= i
    chunks << array[start..last] || []
    start = last+1
  end
  chunks
end

# use as array.chunk
class Array
  def chunk(pieces=2)
    len = self.length;
    mid = (len/pieces)
    chunks = []
    start = 0
    1.upto(pieces) do |i|
      last = start+mid
      last = last-1 unless len%pieces >= i
      chunks << self[start..last] || []
      start = last+1
    end
    chunks
  end
end



Examples of use:

>> chunk_array [1,2,3,4,5,6], 2
=> [[1, 2, 3], [4, 5, 6]]

>> chunk_array [1,2,3,4,5,6], 3
=> [[1, 2], [3, 4], [5, 6]]

>> chunk_array [1,2,3,4,5,6], 4
=> [[1, 2], [3, 4], [5], [6]]

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

>> chunk_array [1,2,3], 4
=> [[1], [2], [3], []]

>> chunk_array [], 2
=> [[], []]


if you prefer the second form (more ruby-ish, but not always appropriate)

>> [1,2,3,4,5,6,7,8,9,10].chunk
=> [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]

>> [1,2,3,4,5,6,7,8,9,10].chunk 3
=> [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]


This is handy when used with a splat because you can do things like:

left, right = *chunk_array(all,2)

Comments on this post

jmcglynn posts on Feb 15, 2007 at 02:45
A shorter format, from "Why's Poignant guide to ruby":

class Array
def / len
a = []
each_with_index do |x,i|
a << [] if i % len == 0
a.last << x
end
a
end
end

[:now, :is, :the, :time, :for, :all, :good, :men, :to, :come, :to, :the, :aid] / 3

gives

=> [[:now, :is, :the], [:time, :for, :all], [:good, :men, :to], [:come, :to, :the], [:aid]]
danology posts on Jun 05, 2007 at 15:12
An even shorter version, using recursion:

class Array
def chunk(pieces)
return [] if pieces.zero?
piece_size = (length.to_f / pieces).ceil
[first(piece_size), *last(length - piece_size).chunk(pieces - 1)]
end
end
vasi posts on Dec 04, 2007 at 01:34
Unfortunately ruby can suffer with deep recursion--though maybe it has tail-call optimization, do you happen to know? Anyhow, here's my pretty short solution:

require 'enumerator'
class Array
def chunk(pieces)
q, r = length.divmod(pieces)
(0..pieces).map { |i| i * q + [r, i].min }.enum_cons(2) \
.map { |a, b| slice(a...b) }
end
end

You need to create an account or log in to post comments to this site.


Click here to browse all 4861 code snippets

Related Posts