字符串增量代码战 (Ruby) 问题

String incrementer codewars (Ruby) problem

我正在开发一个关于 codewars 的字符串增量器项目。 基本上, 编写一个递增字符串的函数,以创建一个新字符串。

如果字符串已经以数字结尾,则该数字应递增 1。 如果字符串不以数字结尾。数字 1 应附加到新字符串。 如果数字有前导零,则应考虑数字的数量。 foo -> foo1

foo001 ->foo002

foobar23 -> foobar24

foo099 -> foo100

我的代码是:input.gsub(/\d/,"")+input.split().map {|x| x[/\d+/].next!}.join(" ") https://repl.it/@tanilserbes/ViolentNoteworthyDowngrade。它适用于这个游乐场 但是它不适用于代码战。我收到此错误:

main.rb:5:在block in increment_string': undefined method下一个!'对于 nil:NilClass (NoMethodError)` 有什么想法吗?
提前致谢!

要查看这里发生了什么,运行 单独执行每个命令并查看输出是什么以跟踪错误是有益的:

input = "foo"
input.gsub(/\d/, "") # => "foo"

因此 + 运算符的左侧将变为 "foo" 现在我们需要查看其右侧是什么:

input.split # => ["foo"]
["foo"].map { |x| x[/\d+/].next! }

正如问题中所见,这是错误发生的地方,所以让我们深入研究 map 块内的代码,错误是:

["foo"].map { |x| p x }
# Outputs: "foo"

所以,x == "foo"此时:

["foo"].map { |x| p x[/\d+/] }
# Outputs: nil

由于字符串 "foo" 中没有任何数字,正则表达式从中提取数字,将它们递增 returns nil 然后,没有任何保护你增加那个。 NilClass 没有方法 next!,所以你得到了你的错误。

如果字符串改为 "foo1",您将得到:

["foo1"].map { |x| p x[/\d+/] }
# Outputs: "1"

其中 returns 匹配的字符串,然后允许您在其上调用 next! (这是注释中调用的 String#succ! 方法的同义词)。它在操场上工作的原因是因为字符串中有数字,并且没有考虑或测试字符串不存在的情况(问题文本中的第一个示例 "foo" 应该成为"foo1").

以下是开发解决方案时需要考虑的一些要点。

如果您的字符串是:

str = "ca9t00456"

所需的 return 值将是:

"ca9t00457"

(请注意,OP 的解决方案将 return 此字符串的结果不正确("cat10")。Codewars 问题并未说明字符串中唯一的数字是末尾的数字;它只提到字符串末尾的 "number"。)

合理的第一步是将字符串分成两部分:

n = str.index(/\d+\z/)
  #=> 4
prefix = str[0, n]
  #=> "ca9t"
suffix = str[n..-1]
  #=> "00456"

参见 String#index. The regular expression, /\d+\z/, reads, "match one or more (+) digits (\d) followed by the end of the string (\z). The digit '9' is skipped over because it is neither followed by a digit nor is at the end of the string. See also See String#[]

我们return的字符串将以(持有的值)prefix开头,所以我们可以暂时搁置它,集中精力修改suffix.

一种方法是:

((suffix.to_i) + 1).to_s
  #=> "457"

但是我们必须添加正确数量的前导零。在这里,它与 suffix (2) 中前导零的数量相同,但是如果 suffix 是,例如 00999,它将只有一个(01000).那是可以做到的,但是太乱了。

更简单的方法是使用方法 String#succ,正如@steenslag 在评论中所建议的那样。

new_suffix = suffix.succ 
  #=> "00457"
"00999".succ
  #=> "01000"

现在我们只需要结合prefixnew_suffix

注意如果我们对整个字符串执行 succ 会发生什么:

"ca9t0456".succ
   #=> "ca9t0457" correct
"ca9t0999".succ
   #=> "ca9t1000" correct
"ca9t9999".succ
   #=> "ca9u0000" incorrect

如您所见,第三个示例存在问题。这就是为什么我选择将字符串分成两部分作为第一步。

您需要调查另外三起案件。第一种是当前缀为空字符串时:

str = "00456"

第二种是当后缀为空字符串时:

str = "ca9t"

第三个是当字符串为空时:

str = ""

您可以检查第一种情况下之前的计算是否仍然有效。

在第二种情况下我们会发现:

n = str.index(/\d+\z/)
  #=> "cat9t".index(/\d+\z/) => nil

nnil 值告诉我们所需的 return 值为:

str + "1"
  #=> "ca9t" + "1" => "ca9t1"

这样行吗?