查找数组中最常见的字符串

我有这个数组,例如(大小是可变的):

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

我需要找到最常用的值(在这种情况下为"1.111" )。

有一个简单的方法吗?

事先提前!

编辑#1:谢谢大家的答案!

编辑#2:我根据ZED的信息更改了我接受的答案。 再次感谢大家!

Ruby <2.2

 #!/usr/bin/ruby1.8 def most_common_value(a) a.group_by do |e| e end.values.max_by(&:size).first end x = ["1.111", "1.122", "1.250", "1.111"] p most_common_value(x) # => "1.111" 

注意: Enumberable.max_by是Ruby 1.9的新增function,但它已被Enumberable.max_by移植到1.8.7

Ruby> = 2.2

Ruby 2.2引入了Object#本身方法,通过它我们可以使代码更简洁:

 def most_common_value(a) a.group_by(&:itself).values.max_by(&:size).first end 

作为猴子补丁

或者作为Enumerable#mode

 Enumerable.class_eval do def mode group_by do |e| e end.values.max_by(&:size).first end end ["1.111", "1.122", "1.250", "1.111"].mode # => "1.111" 

一次通过哈希来累积计数。 使用.max()查找具有最大值的哈希条目。

 #!的/ usr / bin中/ruby

 a = Hash.new(0)
 [“1.111”,“1.122”,“1.250”,“1.111”]。每个{| num |
   a [num] + = 1
 }

 a.max {| a,b |  a [1] <=> b [1]}#=> [“1.111”,2]

或者,将它们全部卷成一行:

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

如果你只想要重新添加项目.first():

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

我使用的第一个样本是如何在Perl中完成的。 第二个是Ruby-ish。 两者都适用于旧版本的Ruby。 我想比较它们,再看看Wayne的解决方案如何加快速度,所以我测试了基准:

 #!/ usr / bin / env ruby

要求'基准'

 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
结束

 n = 1000
 Benchmark.bm(20)do | x |
   x.report(“Hash.new(0)”)做
     n次 
       a = Hash.new(0)
       ary.each {| num |  a [num] + = 1}
       a.max {| a,b |  a [1] <=> b [1]} .first
    结束 
  结束

   x.report(“inject:”)做
     n次
       ary.inject(Hash.new(0)){| h,i |  h [i] + = 1;  h} .max {| a,b |  a [1] <=> b [1]} .first
    结束
  结束

   x.report(“most_common_value():”)做
     n次
       most_common_value(元)
    结束
  结束
结束

结果如下:

                          用户系统总真实
 Hash.new(0)2.150000 0.000000 2.150000(2.164180)
注入:2.440000 0.010000 2.450000(2.451466)
 most_common_value():1.080000 0.000000 1.080000(1.089784)

您可以对数组进行排序,然后循环一次。 在循环中,只需跟踪当前项目及其显示的次数。 列表结束或项目更改后,如果count > max_count ,则设置max_count == count 。 当然要跟踪哪个项目有max_count

您可以创建一个hashmap,将数组项存储为键,其值是元素在数组中出现的次数。

伪代码:

 ["1.111", "1.122", "1.250", "1.111"].each { |num| count=your_hash_map.get(num) if(item==nil) hashmap.put(num,1) else hashmap.put(num,count+1) } 

如前所述,排序可能会更快。

使用散列的默认值function:

 >> x = ["1.111", "1.122", "1.250", "1.111"] >> h = Hash.new(0) >> x.each{|i| h[i] += 1 } >> h.max{|a,b| a[1] <=> b[1] } ["1.111", 2] 

它将返回数组中最受欢迎的值

 x.group_by{|a| a }.sort_by{|a,b| b.size<=>a.size}.first[0] 

IE:

 x = ["1.111", "1.122", "1.250", "1.111"] # Most popular x.group_by{|a| a }.sort_by{|a,b| b.size<=>a.size}.first[0] #=> "1.111 # How many times x.group_by{|a| a }.sort_by{|a,b| b.size<=>a.size}.first[1].size #=> 2