我正在尝试编写代码来确定字符串中字母的连续频率。
例如:
"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
答案 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")