如何编写一个查找字符串中最常见字母的方法?

时间:2015-07-23 01:55:51

标签: ruby string methods

这是问题提示:

  

编写一个接收foo1-ext foo2-ext foo3-ext 的方法。您的方法应该返回数组中最常见的字母,以及它出现的次数。

我不完全确定到目前为止我要去哪里。

string

6 个答案:

答案 0 :(得分:3)

我建议您使用计数哈希:

str = "The quick brown dog jumped over the lazy fox."

str.downcase.gsub(/[^a-z]/,'').
             each_char.
             with_object(Hash.new(0)) { |c,h| h[c] += 1 }.
             max_by(&:last)
   #=> ["e",4]
参数为零的

Hash::new会创建一个空哈希,其默认值为零。

步骤:

s = str.downcase.gsub(/[^a-z]/,'')
  #=> "thequickbrowndogjumpedoverthelazyfox"
enum0 = s.each_char
  #=> #<Enumerator: "thequickbrowndogjumpedoverthelazyfox":each_char>  
enum1 = enum0.with_object(Hash.new(0))
  #=> #<Enumerator: #<Enumerator:
  #    "thequickbrowndogjumpedoverthelazyfox":each_char>:with_object({})> 

您可以将enum1视为“复合”枚举器。 (研究上面的返回值。)

让我们看看enum1

的元素
enum1.to_a
  #=> [["t", {}], ["h", {}], ["e", {}], ["q", {}],..., ["x", {}]] 

enum1["t", {}])的第一个元素由String#each_char传递给块并分配给块变量:

c,h = enum1.next
  #=> ["t", {}] 
c #=> "t" 
h #=> {} 

然后执行块计算:

h[c] += 1
  #=> h[c] = h[c] + 1
  #=> h["t"] = h["t"] + 1
  #=> h["t"] = 0 + 1 #=> 1
h #=> {"t"=>1}

Ruby将h[c] += 1扩展为h[c] = h[c] + 1h["t"] = h["t"] + 1作为h #=> {}h没有键"t",所以{{1}在等号的右侧,由哈希的默认值h["t"]替换。下次0时,c #=> "t"将减少为h["t"] = h["t"] + 1(即,不会使用默认值,因为h["t"] = 1 + 1 #=> 2现在有一个键h)。

然后将"t"的下一个值传递到块中并执行块计算:

enum1

c,h = enum1.next #=> ["h", {"t"=>1}] h[c] += 1 #=> 1 h #=> {"t"=>1, "h"=>1} 的其余元素的处理方式相似。

答案 1 :(得分:1)

一种简单的方法,不用担心检查空字母:

letter, count = ('a'..'z')
                .map {|letter| [letter, string.count(letter)] }
                .max_by(&:last)

答案 2 :(得分:1)

def most_common_letter(string)
  string.downcase.split('').group_by(&:itself).map { |k, v| [k, v.size] }.max_by(&:last)
end

修改
使用哈希:

def most_common_letter(string)
  chars             = {}
  most_common       = nil
  most_common_count = 0
  string.downcase.gsub(/[^a-z]/, '').each_char do |c|
    count = (chars[c] = (chars[c] || 0) + 1)
    if count > most_common_count
      most_common       = c
      most_common_count = count
    end
  end
  [most_common, most_common_count]
end

答案 3 :(得分:1)

这是另一种做你想做的事情:

str = 'aaaabbbbcd'
h = str.each_char.with_object(Hash.new(0)) { |c,h| h[c] += 1 }
max = h.values.max
output_hash = Hash[h.select { |k, v| v == max}]
puts "most_frequent_value: #{max}"
puts "most frequent character(s): #{output_hash.keys}"

答案 4 :(得分:0)

char, count = string.split('').                  
                     group_by(&:downcase).
                     map { |k, v| [k, v.size] }.
                     max_by { |_, v| v }

答案 5 :(得分:0)

我想提到一种由{strong> Ruby 2.7.0 引入的Enumerable#tally解决方案:

str =<<-END
Tallies the collection, i.e., counts the occurrences of each element. Returns a hash with the elements of the collection as keys and the corresponding counts as values.
END

str.scan(/[a-z]/).tally.max_by(&:last)
#=> ["e", 22]


其中:

str.scan(/[a-z]/).tally
#=> {"a"=>8, "l"=>9, "i"=>6, "e"=>22, "s"=>12, "t"=>13, "h"=>9, "c"=>11, "o"=>11, "n"=>11, "u"=>5, "r"=>5, "f"=>2, "m"=>2, "w"=>1, "k"=>1, "y"=>1, "d"=>2, "p"=>1, "g"=>1, "v"=>1}