我有一个相当简单的正则表达式,但我想使用命名正则表达式使其更清晰,然后迭代结果.
测试字符串:
testing_string = "111x222b333"
Run Code Online (Sandbox Code Playgroud)
我的正则表达式:
regexp = %r{
(?<width> [0-9]{3} ) {0}
(?<height> [0-9]{3} ) {0}
(?<depth> [0-9]+ ) {0}
\g<width>x\g<height>b\g<depth>
}x
dimensions = regexp.match(testing_string)
Run Code Online (Sandbox Code Playgroud)
这项工作就像一个魅力,但问题来自何处:
dimensions.each { |k, v| dimensions[k] = my_operation(v) }
# ERROR !
undefined method `each' for #<MatchData "111x222b333" width:"111" height:"222" depth:"333">.
Run Code Online (Sandbox Code Playgroud)
没有.each在MatchData对象中的方法,我真的不想修补它.
我该如何解决这个问题?
我不像我想的那么清楚:重点是保持名称和类似哈希的结构.
Phr*_*ogz 37
如果你需要一个完整的哈希:
captures = Hash[ dimensions.names.zip( dimensions.captures ) ]
p captures
#=> {"width"=>"111", "height"=>"222", "depth"=>"333"}
Run Code Online (Sandbox Code Playgroud)
如果您只想迭代名称/值对:
dimensions.names.each do |name|
value = dimensions[name]
puts "%6s -> %s" % [ name, value ]
end
#=> width -> 111
#=> height -> 222
#=> depth -> 333
Run Code Online (Sandbox Code Playgroud)
备择方案:
dimensions.names.zip( dimensions.captures ).each do |name,value|
# ...
end
[ dimensions.names, dimensions.captures ].transpose.each do |name,value|
# ...
end
dimensions.names.each.with_index do |name,i|
value = dimensions.captures[i]
# ...
end
Run Code Online (Sandbox Code Playgroud)
因此,今天发布了一个新的Ruby版本(2.4.0),其中包括许多新功能,其中包括#11999,又名MatchData#named_captures。这意味着您现在可以执行以下操作:
h = '12'.match(/(?<a>.)(?<b>.)(?<c>.)?/).named_captures
#=> {"a"=>"1", "b"=>"2", "c"=>nil}
h.class
#=> Hash
Run Code Online (Sandbox Code Playgroud)
因此,在您的代码更改中
dimensions = regexp.match(testing_string)
Run Code Online (Sandbox Code Playgroud)
至
dimensions = regexp.match(testing_string).named_captures
Run Code Online (Sandbox Code Playgroud)
您也可以each像在其他正则表达式匹配结果上一样使用该方法Hash。