Ruby不一致的结果与扫描的字符串长度

时间:2017-04-28 23:07:51

标签: ruby regex regex-group

我可能没有这里的全部图片,但我得到的计算结果不一致:我正在尝试解决运行长度编码问题,这样如果你得到一个像“AAABBAAACCCAA”这样的输入字符串,编码将是:“ 3A2B3A3C2A“所以功能是:

def encode(input)
 res = ""
 input.scan(/(.)\1*/i) do |match|
   res << input[/(?<bes>#{match}+)/, "bes"].length.to_s << match[0].to_s
 end
 res
end

我得到的结果是:

irb(main):049:0> input = "AAABBBCCCDDD"
=> "AAABBBCCCDDD" 
irb(main):050:0> encode(input)
(a) => "3A3B3C3D" 
irb(main):051:0> input = "AAABBBCCCAAA"
=> "AAABBBCCCAAA"
irb(main):052:0> encode(input)
(b) => "3A3B3C3A" 
irb(main):053:0> input = "AAABBBCCAAA"
=> "AAABBBCCAAA"
irb(main):054:0> encode(input)
(c) => "3A3B2C3A"
irb(main):055:0> input = "AAABBBCCAAAA"
=> "AAABBBCCAAAA"
irb(main):056:0> encode(input)
(d) => "3A3B2C3A"
irb(main):057:0> input = 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB'
=> "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB"
irb(main):058:0> encode(input)
(e) => "12W1B12W1B12W1B"

正如你所看到的,结果(a)到(c)是正确的,但结果(d)和(e)缺少一些重复,结果代码是几个字母短,你能给出一个提示,在哪里请检查? (我现在正在学习'撬')

2 个答案:

答案 0 :(得分:4)

正则表达式很棒,但它们不是解决每个问题的金钥匙。

str = "AAABBAAACCCAA"
str.chars.chunk_while { |i, j| i == j }.map { |a| "#{a.size}#{a.first}" }.join 

分解它的作用:

str = "AAABBAAACCCAA"
str.chars # => ["A", "A", "A", "B", "B", "A", "A", "A", "C", "C", "C", "A", "A"]
  .chunk_while { |i, j| i == j } # => #<Enumerator: #<Enumerator::Generator:0x007fc1998ac020>:each>
  .to_a # => [["A", "A", "A"], ["B", "B"], ["A", "A", "A"], ["C", "C", "C"], ["A", "A"]]
  .map { |a| "#{a.size}#{a.first}" } # => ["3A", "2B", "3A", "3C", "2A"]
  .join  # => "3A2B3A3C2A"

to_a有说明之处,但没有必要:

str = "AAABBAAACCCAA"
str.chars
  .chunk_while { |i, j| i == j }
  .map { |a| "#{a.size}#{a.first}" }
  .join  # => "3A2B3A3C2A"
  

你怎么知道像Array#chunk_while这样的方法?我使用的是Ruby 2.3.1但是在API文档中找不到它,我的意思是,所有可用方法的概要列表在哪里?当然不是在这里ruby-doc.org/core-2.3.1/Array.html

嗯,这不是问题的主题,但要了解它是有用的信息:

请记住,Array包含Enumerable模块,其中包含chunk_while。使用http://ruby-doc.org的搜索功能查找内容。另外,熟悉在命令行使用ri,并尝试在命令行运行gem server以获取您已安装的所有gem的帮助。

如果你查看Array文档页面,在左边你可以看到Array有一个Object类的父类,所以它有来自Object的方法,并且它也继承自Enumerable,所以它还会引入Enumerable中实现的任何内容。

答案 1 :(得分:1)

您只能获得首先出现的匹配符号重复次数。您需要在gsub内执行替换并将匹配对象传递给可以执行必要操作的块:

def encode(input)
 input.gsub(/(.)\1*/) { |m| m.length.to_s << m[0] }
end

请参阅online Ruby test

结果:

"AAABBBCCCDDD" => 3A3B3C3D
"AAABBBCCCAAA" => 3A3B3C3A
"AAABBBCCAAA" => 3A3B2C3A
"AAABBBCCAAAA" => 3A3B2C4A
"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB" => 12W1B12W3B24W1B