Best way to split arrays into multiple small arrays in ruby

后端 未结 4 456
别跟我提以往
别跟我提以往 2020-12-17 09:47

What is the simplest way to split arrays into multiple arrays based on some conditions? In my scenario, I need to move the integer and the string values to different arrays.

相关标签:
4条回答
  • 2020-12-17 10:34

    Here is my solution:

    hash = x.group_by { |t| t.kind_of? Fixnum }
    # hash  => {true=>[1, 2, 3, 4], false=>["a", "b"]} 
    array1 = hash[true] # The array of integers
    array2 = hash[false] # The array of strings
    
    0 讨论(0)
  • 2020-12-17 10:36

    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"]]
    
    0 讨论(0)
  • 2020-12-17 10:43

    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"]]]
    
    0 讨论(0)
  • 2020-12-17 10:44

    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] * 100
    n = 10_000
    Benchmark.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)
    
    0 讨论(0)
提交回复
热议问题