Partitioning an array with Array#collect_every and Array#subdivide
http://redhanded.hobix.com/bits/matchingIntoMultipleAssignment.html
Author: Ezra Zygmuntowicz (in the comments)
# --------------------------------------------------------------------------- # collect_every(n [,fill=false[,offset=0]]) => an array # collect_every(n [,fill=false[,offset=0]]) {|item| block} => an_array # --------------------------------------------------------------------------- # If a block is given, it invokes the block passing in an array of n elements. # The last array passed may not contain n elements if size % 2 does not equal # zero. If no block is given, it returns an array containing the collections. # # If the optional argument fill is set to true, the empty spaces will be # filled with nils. The optional argument offset allows the collection to # start at that index in the array. # # a = (1..10).to_a # a.collect_every(5) #=> [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]] # a.collect_every(5) {|x| p x} #=> [1, 2, 3, 4, 5] # [6, 7, 8, 9, 10] # b = (1..7).to_a # b.collect_every(3) #=> [[1, 2, 3], [4, 5, 6], [7]] # b.collect_every(3,true) #=> [[1, 2, 3], [4, 5, 6], [7,nil,nil]] # b.collect_every(3,true,1) #=> [[2, 3, 4], [5, 6, 7]] class Array def collect_every(n, fill=false, offset = 0) if block_given? while offset < size ret = [] if fill n.times do |x| if offset + x > size - 1 then ret << nil else ret << self[offset + x] end end else n.times { |x| ret << self[offset + x] unless offset + x > size - 1} end offset += n yield ret ret = nil end else ret = [] while offset < size ret << [] if fill n.times do |x| if offset + x > size - 1 then ret.last << nil else ret.last << self[offset + x]; end end else n.times { |x| ret.last << self[offset + x] unless offset + x > size - 1 } end offset += n end return ret end end end a = (1..10).to_a puts a.collect_every(5).inspect #-> [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]] a.collect_every(5) { |x| puts x.inspect } #-> [1, 2, 3, 4, 5] and [6, 7, 8, 9, 10] puts a.collect_every(3, true).inspect #-> [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, nil, nil]] puts a.collect_every(3, true,1).inspect #-> [[2, 3, 4], [5, 6, 7], [8, 9, 10]] puts a.collect_every(3, true,4).inspect #-> [[5, 6, 7], [8, 9, 10]] puts a.inspect #-> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # ------------------------------------------------------------------------ class Array def subdivide(n) return self if n <= 0 || n >= self.size result = [] max_subarray_size = n - 1 while self.size > 0 result << self.slice!(0..max_subarray_size) end result end end a = ('a'..'g').to_a b = a.subdivide(3) puts b.inspect #-> [["a", "b", "c"], ["d", "e", "f"], ["g"]] puts a.inspect #-> []