连续的字母频率

时间:2014-12-30 22:19:26

标签: ruby

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

例如:

"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

7 个答案:

答案 0 :(得分:9)

p "aabbcbb".chars.chunk{|c| c}.map{|c, a| [c, a.size]} 
# => [["a", 2], ["b", 2], ["c", 1], ["b", 2]]

答案 1 :(得分:6)

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

答案 2 :(得分:4)

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

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

但我更倾向于chunk method以获得清晰度(几乎可以肯定是效率)。


实际上出于好奇,我写了一个快速基准测试,scan比<{1}} > 比<{1}}快了四倍,但我 仍然使用chunk.map以保持清晰,除非您实际上已经成功执行了数十万次:

chunk.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

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

@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]]

答案 5 :(得分:0)

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

答案 6 :(得分:-2)

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

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")