Find most common string in an array

前端 未结 6 1888
说谎
说谎 2020-12-24 07:42

I have this array, for example (the size is variable):

   x = [\"1.111\", \"1.122\", \"1.250\", \"1.111\"]

and I need to find the most comm

6条回答
  •  粉色の甜心
    2020-12-24 08:12

    One pass through the hash to accumulate the counts. Use .max() to find the hash entry with the largest value.

    #!/usr/bin/ruby
    
    a = Hash.new(0)
    ["1.111", "1.122", "1.250", "1.111"].each { |num|
      a[num] += 1
    }
    
    a.max{ |a,b| a[1] <=> b[1] } # => ["1.111", 2]
    

    or, roll it all into one line:

    ary.inject(Hash.new(0)){ |h,i| h[i] += 1; h }.max{ |a,b| a[1] <=> b[1] } # => ["1.111", 2]
    

    If you only want the item back add .first():

    ary.inject(Hash.new(0)){ |h,i| h[i] += 1; h }.max{ |a,b| a[1] <=> b[1] }.first # => "1.111"
    

    The first sample I used is how it would be done in Perl usually. The second is more Ruby-ish. Both work with older versions of Ruby. I wanted to compare them, plus see how Wayne's solution would speed things up so I tested with benchmark:

    #!/usr/bin/env ruby
    
    require 'benchmark'
    
    ary = ["1.111", "1.122", "1.250", "1.111"] * 1000 
    
    def most_common_value(a)
      a.group_by { |e| e }.values.max_by { |values| values.size }.first
    end
    
    n = 1000
    Benchmark.bm(20) do |x|
      x.report("Hash.new(0)") do
        n.times do 
          a = Hash.new(0)
          ary.each { |num| a[num] += 1 }
          a.max{ |a,b| a[1] <=> b[1] }.first
        end 
      end
    
      x.report("inject:") do
        n.times do
          ary.inject(Hash.new(0)){ |h,i| h[i] += 1; h }.max{ |a,b| a[1] <=> b[1] }.first
        end
      end
    
      x.report("most_common_value():") do
        n.times do
          most_common_value(ary)
        end
      end
    end
    

    Here's the results:

                              user     system      total        real
    Hash.new(0)           2.150000   0.000000   2.150000 (  2.164180)
    inject:               2.440000   0.010000   2.450000 (  2.451466)
    most_common_value():  1.080000   0.000000   1.080000 (  1.089784)
    

提交回复
热议问题