**更新
现在我在做
a = gets
count = ((a.match(/d+/)).to_s).to_i.
样本输入:3.00 的2000
实际产量:2000
样本输入:2000 中的3.00
实际输出:3
目标输出:两种情况下均为2000(跳过浮动)
"3.00 of 2000"[/(?<![.d])d+(?![.d])/].to_i # => 2000
"2000 of 3.00"[/(?<![.d])d+(?![.d])/].to_i # => 2000
这是您必须了解数据的情况之一。如果你知道你的输入总是只有一个整数,那么下面的方法会起作用:
'3.00 of 2000'.split.select { |e| e =~ /^d+$/ }.last.to_i
#=> 2000
'2000 of 3.00'.split.select { |e| e =~ /^d+$/ }.last.to_i
#=> 2000
其想法是将每一行输入拆分为一个数组,然后只选择只包含数字的数组元素。最后,数组的最后一个(希望也是唯一一个)元素被转换为整数。
在给定任意输入的情况下,有很多方法可能会失败或无法实现您想要的结果。然而,它确实适用于您提供的特定语料库。
使用代码:
a = gets
a.split(/[sa-z]+/).select {| v | v !~ /./ }.last.to_i
# => 2000
没有正则表达式,但。。。
'2000 to 3.00'.split.find { |s| s.to_i.to_s == s }.to_i
=> 2000
'3.00 to 2000'.split.find { |s| s.to_i.to_s == s }.to_i
=> 2000
正则表达式[^0-9.]([0-9]+)[^0-9]
将只匹配与非数字或点字符相邻的数字,并捕获单个捕获组中的数字。
如果数字也可以出现在字符串的开头或结尾附近,则修复应该是不言而喻的;
(?:^|[^0-9.])([0-9]+)(?:[^0-9.]|$)
str = '3 of 20.00, +42,31 of 455, -6 of -23.7 .'
str.scan(/(?<![.d])(-?d+)(?!d*.)/).flatten.map(&:to_i)
=> [3, 42, 31, 455, -6]
- 捕获组
(-?d+)
由一个或多个数字0-9组成,可选地在数字0-9前面加一个减号 (?<![.d])
是一个负查找组,这意味着捕获组前面不能有小数点或数字(?!d*.)/)
是一个负前瞻组,这意味着捕获组后面不能跟零个或多个数字,后面跟一个小数点str.scan(/(?<![.d])(-?d+)(?!d*.)/) #=> [["3"], ["42"], ["31"], ["455"], ["-6"]]
,这就是为什么在转换为整数之前必须应用flatten
- 最初,我尝试将
(?<!.d*)
作为负后备组,但这产生了一个错误。原因是:负lookbehinds不能是可变长度的。我知道Perl中也有同样的限制
编辑:我不知怎么忽略了问题的标题。要只检索第一个整数,请在str.scan
的末尾加上.first
,或者将该语句替换为:
str.match(/(?<![.d])(-?d+)(?!d*.)/)[0].to_i
words_containing_non_digits = -> x {x[/D/]}
p '3.00 of 2000'.split.reject &words_containing_non_digits #=> ["2000"]