Ruby计数字符序列不使用正则表达式

在计算序列中的字符时需要有关此代码的帮助。

这就是我要的:

word("aaabbcbbaaa") == [["a", 3], ["b", 2], ["c", 1], ["b", 2], ["a", 3]] word("aaaaaaaaaa") == [["a", 10]] word("") == [] 

这是我的代码:

 def word(str) words=str.split("") count = Hash.new(0) words.map {|char| count[char] +=1 } return count end 

我得到了一句话(“aaabbcbbaaa”)=> [[“a”,6],[“b”,4],[“c”,1]],这不是我想要的。 我想计算每个序列。 我更喜欢没有正则表达式的解决方案。 谢谢。

按字符分割字符串,然后按字符串分组,然后计算字符串中的字符数:

 def word str str .chars .chunk{ |e| e } .map{|(e,ar)| [e, ar.length] } end p word "aaabbcbbaaa" p word("aaaaaaaaaa") p word "" 

结果:

 [["a", 3], ["b", 2], ["c", 1], ["b", 2], ["a", 3]] [["a", 10]] [] 

如果您不想使用正则表达式,您可能只需要执行以下操作:

 def word(str) last, n, result = str.chars.first, 0, [] str.chars.each do |char| if char != last result << [last, n] last, n = char, 1 else n += 1 end end result << [last, n] end 

我想使用一些高阶函数来使这更简洁,但Ruby标准库中没有适当的函数。 Enumerable#partition几乎可以做到,但并不完全。

我会做以下事情。 请注意, each_char是一个较新的方法(Ruby 1.9?),可能在您的版本中不可用,因此在这种情况下坚持使用words=str.split("")

 def word(str) return [] if str.length == 0 seq_count = [] last_char = nil count = 0 str.each_char do |char| if last_char == char count += 1 else seq_count << [last_char, count] unless last_char.nil? count = 1 end last_char = char end seq_count << [last_char, count] end [52] pry(main)> word("hello") => [["h", 1], ["e", 1], ["l", 2], ["o", 1]] [54] pry(main)> word("aaabbcbbaaa") => [["a", 3], ["b", 2], ["c", 1], ["b", 2], ["a", 3]] [57] pry(main)> word("") => [] 

另一个非正则表达式版本。

 x = "aaabbcbbaaa" def word(str) str.squeeze.reverse.chars.each_with_object([]) do |char, list| count = 0 count += 1 until str.chomp!(char).nil? list << [char, count] end end p word(x) #=> [["a", 3], ["b", 2], ["c", 1], ["b", 2], ["a", 3]] 

如果世界没有regexchunk

 def word(str) a = str.chars b = [] loop do return b if a.empty? c = a.slice_before {|e| e != a.first}.first b << [c.first, c.size] a = a[c.size..-1] end end word "aaabbcbbaaa" # => [["a", 3], ["b", 2], ["c", 1], ["b", 2], ["a", 3]] word "aaa" # => [["a",3]] word "" # => [] 

这是另一种方式。 最初,我试图找到一个不需要将字符串转换为字符数组的解决方案。 在我看到@hirolau的答案之前,我无法想出任何体面的东西,我修改过:

 def word(str) list = [] char = str[-1] loop do return list if str.empty? count = 0 count += 1 until str.chomp!(char).nil? list.unshift [char, count] char = str[-1] end end 

您可以在扫描中使用此模式:

 "aaabbcbbaaa".scan(/((.)\2*)/) 

并计算所有组1的字符数

例:

 "aaabbcbbaaaa".scan(/((.)\2*)/).map do |x,y| [y, x.length] end