连续的字母频率

我正在尝试编写代码来确定字符串中字母的连续频率。

例如:

"aabbcbb" => ["a",2],["b",2],["c", 1], ["b", 2] 

我的代码给了我第一个字母频率,但没有继续下一个。

 def encrypt(str) array = [] count = 0 str.each_char do |letter| if array.empty? array << letter count += 1 elsif array.last == letter count += 1 else return [array, count] array = [] end end end 

 p "aabbcbb".chars.chunk{|c| c}.map{|c, a| [c, a.size]} # => [["a", 2], ["b", 2], ["c", 1], ["b", 2]] 
 "aabbcbb".chars.slice_when(&:!=).map{|a| [a.first, a.length]} # => [["a", 2], ["b", 2], ["c", 1], ["b", 2]] 

有一个简单的基于正则表达式的解决方案涉及反向引用:

 "aabbbcbb".scan(/((.)\2*)/).map { |m,c| [c, m.length] } # => [["a", 2], ["b", 3], ["c", 1], ["b", 2]] 

但我更倾向于使用chunk方法来提高清晰度(几乎可以肯定是效率)。


实际上出于好奇,我写了一个快速的基准测试, scan 速度chunk.map chunk.map ,但我仍然使用chunk.mapchunk.map ,除非你真的这样做了几十万次:

 require 'benchmark' N = 10000 data = ('a'..'z').map { |c| c * 10 }.join("") Benchmark.bm do |bm| bm.report do N.times { data.chars.chunk{ |c| c }.map { |c, a| [c, a.size] } } end bm.report do N.times { data.scan(/((.)\2*)/).map { |m,c| [c, m.size] } } end end 
  user system total real 0.800000 0.010000 0.810000 ( 0.803824) 0.190000 0.000000 0.190000 ( 0.192915) 

你需要建立一个结果数组,而不是简单地停在第一个结果:

 def consecutive_frequencies(str) str.each_char.reduce([]) do |frequencies_arr, char| if frequencies_arr.last && frequencies_arr.last[0] == char frequencies_arr.last[1] += 1 else frequencies_arr << [char, 1] end frequencies_arr end end 

@steenslag给出了我给出的答案,所以我会尝试不同的东西。

 "aabbcbb".each_char.with_object([]) { |c,a| (a.any? && c == a.last.first) ? a.last[-1] += 1 : a << [c, 1] } #=> [["a", 2], ["b", 2], ["c", 1], ["b", 2]] 
 def encrypt(str) count = 0 array = [] str.chars do |letter| if array.empty? array << letter count += 1 elsif array.last == letter count += 1 else puts "[#{array}, #{count}]" array.clear count = 0 array << letter count += 1 end end puts "[#{array}, #{count}]" end 

你的实现有几个错误,我会尝试使用哈希(而不是数组)并使用这样的东西:

 def encrypt(str) count = 0 hash = {} str.each_char do |letter| if hash.key?(letter) hash[letter] += 1 else hash[letter] = 1 end end return hash end puts encrypt("aabbcbb")