MatchData の名前付き一致をハッシュに変換する
概要
かなり単純な正規表現がありますが、名前付き正規表現を使用してそれをクリーンにし、結果を反復処理したいと考えました。
テスト文字列:
testing_string = "111x222b333"
私の正規表現:
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)
これは魅力的に機能しますが、ここで問題が発生します。
dimensions.each { |k, v| dimensions[k] = my_operation(v) }
# ERROR !
undefined method `each' for #<MatchData "111x222b333" width:"111" height:"222" depth:"333">.
MatchData オブジェクトには .each メソッドがないので、モンキーパッチを適用したくありません。
この問題はどうすれば解決できますか?
思ったほど明確ではありませんでした。重要なのは、名前とハッシュのような構造を維持することです。
解決策
完全なハッシュが必要な場合:
captures = Hash[ dimensions.names.zip( dimensions.captures ) ]
p captures
#=> {"width"=>"111", "height"=>"222", "depth"=>"333"}
名前と値のペアを反復処理するだけの場合は、次のようにします。
dimensions.names.each do |name|
value = dimensions[name]
puts "%6s -> %s" % [ name, value ]
end
#=> width -> 111
#=> height -> 222
#=> depth -> 333
代替案:
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