Best way to split arrays into multiple small arrays in ruby Best way to split arrays into multiple small arrays in ruby ruby ruby

Best way to split arrays into multiple small arrays in ruby


You're looking for Enumerable#partition:

x = [1, 2, 3, "a", "b", 4]numbers, not_numbers = x.partition{|item| item.kind_of?(Fixnum)}# => [[1, 2, 3, 4], ["a", "b"]]


Just to throw some more solutions into the pool:

x = [1,2,3,"a","b",4]numbers = x.select{ |e| e.is_a?(Fixnum) } # => [1, 2, 3, 4]letters = x - numbers # => ["a", "b"]numbers = x.select{ |e| e.kind_of?(Fixnum) } # => [1, 2, 3, 4]letters = x - numbers # => ["a", "b"]

or

(numbers, letters) = x.group_by {|a| a.class}.values_at(Fixnum, String)numbers # => [1, 2, 3, 4]letters # => ["a", "b"]

Along with some benchmarks showing how a subtle change effects speed:

require 'benchmark'x = [1,2,3,"a","b",4] * 100n = 10_000Benchmark.bm do |bench|  bench.report { n.times {    numbers = x.select{ |e| e.is_a?(Fixnum) }    letters = x - numbers  }}  bench.report { n.times {    numbers = x.select{ |e| e.kind_of?(Fixnum) }    letters = x - numbers  }}  bench.report { n.times {    (numbers, letters) = x.group_by {|a| a.class}.values_at(Fixnum, String)  }}  bench.report { n.times {    numbers, not_numbers = x.partition{|item| item.kind_of? Fixnum}  }}end# >>       user     system      total        real# >>   4.270000   0.010000   4.280000 (  4.282922)# >>   4.290000   0.000000   4.290000 (  4.288720)# >>   5.160000   0.010000   5.170000 (  5.163695)# >>   3.720000   0.000000   3.720000 (  3.721459)


Try:

x.group_by {|x| x.class}

You can get an array back by then calling to_a on the result which in the example you've given will return:

[[Fixnum, [1, 2, 3, 4]], [String, ["a", "b"]]]