From: Logan Capaldo Date: 2006-07-21T12:28:23+09:00 Subject: Re: how to split an array in sub arrays of the same length On Jul 20, 2006, at 4:40 PM, Phrogz wrote: > Paolo Bacchilega wrote: >> Is there a way to split an array in sub arrays of the same length, >> that > > Stolen from the facets[1] extensions for Arrays[2]: > > class Array > def each_slice(n=nil, &yld) > n = yld.arity.abs unless n > i=0 > while i < self.length > yld.call(*self.slice(i,n)) > i+=n > end > end > end > > [1] http://facets.rubyforge.org/ > [2] http://facets.rubyforge.org/api/core/classes/Array.html#M000163 > > This is in enumerator, enumerator comes with ruby. Do we really need an "Optimized for Array" version? (That is its purpose according to the docs.) Well surprising to me, there really is a noticeable speed difference. I gues sit makes sense, each_slice in enumerator.c is written to use each, and not just call to_a first either. (Which makes sense, Files are Enumerables after all, maybe you want it in chunks of N lines at a time. You wouldn't want to have to slurp the whole file into memory just to do that). I wonder if we can get this each_slice stuck in the standard lib for Array. % cat enumerator_vs_facets.rb #!/usr/bin/env ruby require 'enumerator' require 'benchmark' class Array def facets_each_slice(n=nil, &yld) n = yld.arity.abs unless n i=0 while i < self.length yld.call(*self.slice(i,n)) i+=n end end end arrays = [ (1..97).to_a, (0..99).to_a, ["hello", "world"] ] N = 1000 Benchmark.bmbm do |bm| bm.report("Facets: ") do N.times do arrays.each do |array| array.facets_each_slice(3) { |*x| "#{x}" } end end end bm.report("Enumerator: ") do N.times do arrays.each do |array| array.each_slice(3) { |*x| "#{x}" } end end end end % ruby enumerator_vs_facets.rb Rehearsal ------------------------------------------------ Facets: 1.250000 0.010000 1.260000 ( 1.364671) Enumerator: 1.380000 0.010000 1.390000 ( 1.442132) --------------------------------------- total: 2.650000sec user system total real Facets: 1.250000 0.010000 1.260000 ( 1.315879) Enumerator: 1.390000 0.010000 1.400000 ( 1.447592)