我正在使用此代码:
s = line.match( /ABCD(\d{4})/ ).values_at( 1 )[0]
从字符串中提取数字,例如:
ABCD1234
ABCD1235
ABCD1236
等等。
它可以工作,但我想知道在 Ruby 中我还有什么其他选择?
我的代码:
ids = []
someBigString.lines.each {|line|
ids << line.match( /ABCD(\d{4})/ ).values_at( 1 )[0]
}
有很多 Ruby 方法,如 http://www.ruby-forum.com/topic/125709
line.scan(/\d/).join('')
line.gsub(/[^0-9]/, '')
line.gsub(/[^\d]/, '')
line.tr("^0-9", '')
line.delete("^0-9")
line.split(/[^\d]/).join
line.gsub(/\D/, '')
在控制台上尝试每个操作。
另请查看该帖子中的基准报告。
还有更简单的解决方案
line.scan(/\d+/).first
a.map {|x| x[/\d+/]}
最简单、最快的方法是使用正则表达式从字符串中解析出整数。
str = 'abc123def456'
str.delete("^0-9")
=> "123456"
str.tr("^0-9","")
=> "123456"
将长字符串上的基准与此处提供的一些其他解决方案进行比较,我们可以看到
tr
最快,delete
接近第二。
require 'benchmark'
n = 2
string = [*'a'..'z'].concat([*1..1_000_000].map(&:to_s)).shuffle.join
Benchmark.bmbm do |x|
x.report('scan') do
n.times {string.scan(/\d/).join}
end
x.report('gsub') do
n.times {string.gsub(/[^\d]/,"")}
end
x.report('gsub2') do
n.times {string.gsub(/\D/, '')}
end
x.report('tr') do
n.times {string.tr("^0-9","")}
end
x.report('delete') do
n.times {string.delete('^0-9')}
end
x.report('split') do
n.times {string.split(/[^\d]/).join}
end
end
Rehearsal ------------------------------------------
scan 3.509973 0.187274 3.697247 ( 3.717773)
gsub 0.229568 0.002790 0.232358 ( 0.233961)
gsub2 0.307728 0.013435 0.321163 ( 0.390262)
tr 0.021395 0.000223 0.021618 ( 0.022297)
delete 0.021290 0.002280 0.023570 ( 0.024365)
split 0.284935 0.010274 0.295209 ( 0.299865)
--------------------------------- total: 4.591165sec
user system total real
scan 3.146615 0.126009 3.272624 ( 3.281860)
gsub 0.211263 0.001515 0.212778 ( 0.213170)
gsub2 0.208482 0.000424 0.208906 ( 0.209339)
tr 0.015228 0.000086 0.015314 ( 0.015387)
delete 0.015786 0.000128 0.015914 ( 0.016050)
split 0.205096 0.002736 0.207832 ( 0.208380)
your_input = "abc1cd2"
your_input.split(//).map {|x| x[/\d+/]}.compact.join("").to_i
这应该有效。
另一种解决方案可能是写:
myString = "sami103"
myString.each_char{ |c| myString.delete!(c) if c.ord<48 or c.ord>57 } #In this case, we are deleting all characters that do not represent numbers.
现在,如果你输入
myNumber = myString.to_i #or myString.to_f
这应该返回一个
数字字符串可以是小数和/或负数。因此:
[string.chr == "-" ? "-" : nil, string.delete("^.0-9")].compact.inject(:+)
chr
方法 来检查字符串是否以负号 -
开头。然后它会删除除数字和小数之外的所有内容,然后在前面添加 -
(如果最初存在)。
这允许使用
to_i
和 to_f
方法进行链接。
compact
从数组中删除 nil(如果它不是负数)inject(:+)
根据数组内容的顺序将数组展平回字符串[
chr == "-" ? "-" : nil,
gsub(%r{[^./0-9[:space:]]}, "").gsub(%r{[[:space:]]*(?<numerator>\d+)[[:space:]]*/[[:space:]]*(?<denominator>\d+)[[:space:]]*}) do
$LAST_MATCH_INFO.named_captures.with_indifferent_access.then do |capture_hash|
Rational(capture_hash.fetch(:numerator, 0), capture_hash.fetch(:denominator, 1)).to_f.to_s.delete_prefix('0')
end
end
].compact.inject(:+).squish
此版本将
/
和 [[:space:]]
添加到例外列表中,以指示除法将在哪里进行,并允许我们利用空格来确定分数的大小。
gsub(%r{[[:space:]]*(?<numerator>\d+)[[:space:]]*/[[:space:]]*(?<denominator>\d+)})
是一个正则表达式,用于查找:
[[:space:]]*
-> 零个或多个空格(?<numerator>\d+)
分子的一组数字[[:space:]]*
-> 零或更多空间(?<denominator>\d+)
一组数字作为分母[[:space:]]*
-> 零或更多空间$LAST_MATCH_INFO.named_captures
为我们提供了命名捕获组和匹配值的哈希值:
"3 1 / 2 cups".gsub(%r{[^./0-9[:space:]]}, "").gsub(%r{[[:space:]]*(?<numerator>\d+)[[:space:]]*/[[:space:]]*(?<denominator>\d+)[[:space:]]*}) do
$LAST_MATCH_INFO.named_captures # => {"numerator"=>"1", "denominator"=>"2" }
end
使用此哈希,我们可以
fetch
并设置默认值,以便在未找到分子和分母时 Rational
始终解析为 0。
.to_f.to_s.delete_prefix('0')
假设分数的分子始终小于分母。这部分代码将分数转换为浮点数,然后转换为字符串,之后 if 从字符串中删除第一个 char
,该字符串预计为零。
Rational(1, 2).to_f # => 0.5
Rational(1, 2).to_f.to_s # => "0.5"
Rational(1, 2).to_f.to_s.delete_prefix('0') # => ".5"
delete_prefix 的基准测试接近最快,但更具可读性,因此我选择它。
最后我们有一个
squish
来清理任何前导或尾随空白,如果您要使用更纯粹的 ruby,也可以使用 strip
。
注意:如果您在此处添加
to_i
和 to_f
方法,则不需要 squish
或 strip
,因为它们对空格并不挑剔,并且在没有空格的情况下也能很好地解析数字。所以你最终可以得到这样的东西来为你添加这些方法:
def numberize(with: :squish)
raise ArgumentError, "with: #{with} is not a valid argument" unless with.in?(%i[squish strip to_i to_f])
[
chr == "-" ? "-" : nil,
gsub(%r{[^./0-9[:space:]]}, "")
.gsub(%r{[[:space:]]*(?<numerator>\d+)[[:space:]]*/[[:space:]]*(?<denominator>\d+)[[:space:]]*}) do
$LAST_MATCH_INFO.named_captures.with_indifferent_access.then do |capture_hash|
Rational(capture_hash.fetch(:numerator, 0), capture_hash.fetch(:denominator, 1)).to_f.to_s.delete_prefix('0')
end
end
].compact.inject(:+).send(with)
end
要从字符串中提取数字部分,请使用以下命令:
str = 'abcd1234'
/\d+/.match(str).try(:[], 0)
它应该返回
1234