0

文字列内のすべての非数字を置き換えるには1行のgsubが必要ですが、非数字が3つ以下で、数字の合計の長さが10の場合のみです

私は最初の条件に合うこれを持っています

p "0177/385490".gsub(/((\d+)\D?(\d+)\D?(\d+)\D?+(\d+))/,'\2\3\4\5') 
#=>"0177385490"

しかし、これを試してみると、{10} チェックが機能しません

p "0177/385490".gsub(/((\d+)\D?(\d+)\D?(\d+)\D?+(\d+)){10}/,'\2\3\4\5') 
#=>"0177/385490"

これを行う方法を教えてください。

編集

私はこのように管理しましたが、これを1行のgsubで行うにはどうすればよいですか?

strings = [
   "0473/385 490",
   "0473/385490",
   "0473 38 54 90",
   "0473/385 4901"    #this one is't captured
 ]

 strings.each do |s|
   if /((\d+)\D?(\d+)\D?(\d+)\D?+(\d+))/ =~ s
     if "#{$2}#{$3}#{$4}#{$5}".length == 10
       puts "#{$2}#{$3}#{$4}#{$5}"
     end
   end
 end

編集: なぜそれが本当にオンライン gsub ここで私のルーチンである必要があるのか​​ を示すために、さらに置換が追加されます

def cleanup text
  replacements = [
     {:pattern => /(04\d{2}) (\d{2}) (\d{2}) (\d{2})/, :replace_with => '\1\2\3\4'},
     {:pattern => /(0\d)(\/| |-)(\d{3}) (\d{2}) (\d{2})/, :replace_with => '\1\3\4\5'},
     {:pattern => /(\d{6} )(\d{3})-(\d{2})/, :replace_with => '\1\2 \3'},
     {:pattern => /(\d{2,4})\D?(\d{2,3})\D?(\d{2,3})/, :replace_with => '\1\2\3'}
  ].each{|replacement|text.gsub!(replacement[:pattern], replacement[:replace_with])}
  text
end
4

5 に答える 5

3

一行gsubは読みすぎないだろうと思います。これが私のアプローチです:

chars, non_chars = s.each_char.partition { |c| c =~ /\d/ }
puts chars.join if chars.size == 10 && non_chars.size <= 3

魔法の変数がなく、すっきりと読みやすい。さらに、文字列に課したルールが明確に示されます。

于 2012-06-21T12:08:15.353 に答える
3

以下は、主に Michael Kohl のアプローチが優れている理由を説明するための、gsub のワンライナーです。

(digits = s.gsub(/\D/, '')).length == 10 && s.length < 14 ? digits : s
于 2012-06-21T12:20:13.320 に答える
1

次のようなものを使用できます。

puts s.gsub(/\D/, '') if (/\A(\d\D?){10}\z/ =~ s) && (/\A(\d+\D){0,3}\d*\z/ =~ s)
于 2012-06-21T12:24:44.987 に答える
1

方法についても知りたいと思うかもしれませんscan

strings.each do |s|
  numbers = s.scan(/\d/).join
  non_numbers = s.scan(/\D/)
  puts numbers if numbers.length == 10 && non_numbers.length < 4
end

しかし、@MichaelKohlによるソリューションの方が好きです。

そして、ばかげた例:

strings.select{|s| s.scan(/\D/).length < 4}.map{|s| s.scan(/\d/).join}.select{|s| s.length==10}
于 2012-06-21T12:32:49.023 に答える
0

皆さんありがとうございますが、ルーチンに挿入できないため、回答を使用できません(より明確にするために回答を編集しました)。自分で解決策を見つけました。要求に応じて 1 行のソリューションを持っていた全員に賛成票を投じますが、クリーンアップ ルーチンでブロックを置換パターンとして挿入する方法を見つける必要があります。

p "0177/3854901".gsub(/(\d+)\D?(\d+)\D?(\d+)\D?+(\d+)/){ |m| "#{$1}#{$2}#{$3}#{$4}".length==10 ? "#{$1}#{$2}#{$3}#{$4}":m} 
#=> "0177/3854901" isn't replaced because it has 11 digits
p "0177/385490".gsub(/(\d+)\D?(\d+)\D?(\d+)\D?+(\d+)/){ |m| "#{$1}#{$2}#{$3}#{$4}".length==10 ? "#{$1}#{$2}#{$3}#{$4}":m} 
#=> "0177385490"
于 2012-06-21T12:42:08.700 に答える