字符串增量代码战 (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"
现在我们只需要结合prefix
和new_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
n
的 nil
值告诉我们所需的 return 值为:
str + "1"
#=> "ca9t" + "1" => "ca9t1"
这样行吗?
我正在开发一个关于 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"
现在我们只需要结合prefix
和new_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
n
的 nil
值告诉我们所需的 return 值为:
str + "1"
#=> "ca9t" + "1" => "ca9t1"
这样行吗?