0

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

如果字符串已经以数字结尾,则该数字应加 1。如果字符串不以数字结尾。数字 1 应附加到新字符串中。如果数字有前导零,则应考虑位数。富 -> 富1

foo001 -> foo002

foob​​ar23 -> 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)` 有什么想法吗?
提前致谢!。

4

2 回答 2

2

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

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"中没有任何数字,因此正则表达式从中提取数字,以增加它们返回nil,然后在没有任何保护措施的情况下增加它。NilClass没有方法next!,所以你得到你的错误。

但是,如果字符串是"foo1",你会得到:

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

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

于 2020-02-24T04:18:44.967 回答
1

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

如果您的字符串是:

str = "ca9t00456"

期望的返回值是:

"ca9t00457"

(请注意,OP 的解决方案会"cat10"为此字符串返回不正确的结果( .)

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

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

请参阅字符串#index。正则表达式 ,/\d+\z/读作“匹配一个或多个 ( +) 数字 ( \d) 后跟字符串 ( \z) 的结尾。该数字'9'被跳过,因为它后面既没有数字也没有在字符串的末尾。请参阅另见字符串#[]

我们返回的字符串将以 (保存的值) 开头prefix,所以我们现在可以把它放在一边,专注于修改suffix

一种方法是:

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

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

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

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

niln告诉我们期望的返回值是:

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

那行得通吗?

于 2020-02-24T07:48:15.880 回答