4

需要有关此代码的有关按顺序计数字符的帮助。

这就是我要的:

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

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

4

6 回答 6

8

按字符拆分字符串,然后按字符分组块,然后按块计算字符:

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]]
[]
于 2013-11-14T04:34:31.470 回答
2

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

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几乎做到了,但不完全。

于 2013-11-14T03:59:30.663 回答
1

我会做以下事情。请注意,这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("")
=> []
于 2013-11-14T04:13:58.150 回答
1

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

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]]
于 2013-11-14T08:10:31.733 回答
1

如果世界没有regexand chunk

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
于 2013-11-14T17:19:24.707 回答
0

您可以将此模式与扫描一起使用:

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

并计算所有组 1 的字符数

例子:

"aaabbcbbaaaa".scan(/((.)\2*)/).map do |x,y| [y, x.length] end
于 2013-11-14T03:46:11.057 回答