変換テーブルのように使用して、ハッシュから始めることをお勧めします。ハッシュ ルックアップは非常に高速で、タグとその置換を適切に整理できます。
hash = {
# old_tag => new_tag
'C#' => 'C-Sharp',
'C Sharp' => 'C-Sharp',
'Crazy' => '',
'C #' => 'C-Sharp',
}
値に多くの冗長性があることがわかります。これは、ハッシュを逆にすることで修正でき、うまく削減できます。
hash = {
# new_tag => old_tag
'C-Sharp' => ['C#', 'C Sharp', 'C #'],
}
'Crazy'
外れ値ですが、対処します。
RubyString.gsub
には、正規表現とハッシュを渡すことができる優れた機能がありますが、ほとんど使用されておらず、すべての正規表現の一致をハッシュ内の同等の値に置き換えます。その正規表現は簡単に構築できます。
regex = /(?:#{ Regexp.union(hash.keys).source })/
=> /(?:C\-Sharp)/
さて、あなたはおそらく「でも待てよ、見つけなければならないタグがもっとたくさんある!」と言っているだろうし、ハッシュが構築される方法のために、それらは値に隠されている. これを改善するために、ハッシュのキーと値を逆にして、値の配列を個々の要素に分解します。
reversed_hash = Hash[hash.flat_map{ |k,v| v.map{ |i| [i,k] } }]
=> {
"C#" => "C-Sharp",
"C Sharp" => "C-Sharp",
"C #" => "C-Sharp",
}
'Crazy'
「特殊なケース」の 2 番目のハッシュをマージすることで、簡単に追加できます。
special_cases = {
'Crazy' => ''
}
reversed_hash = Hash[hash.flat_map{ |k,v| v.map{ |i| [i,k] } }].merge(special_cases)
=> {
"C#" => "C-Sharp",
"C Sharp" => "C-Sharp",
"C #" => "C-Sharp",
"Crazy" => ""
}
それを正規表現ビルドコードで使用する:
regex = /(?:#{ Regexp.union(reversed_hash.keys).source })/
=> /(?:C\#|C\ Sharp|C\ \#|Crazy)/
自動生成された正規表現を使用してタグを見つけます。大文字と小文字を区別しない必要がある場合は、次を使用します。
regex = /(?:#{ Regexp.union(reversed_hash.keys).source })/i
テストするテキストの作成:
text =<<EOT
This is "#C#"
This is "C Sharp"
This is "C #"
This is "Crazy"
EOT
=> "This is \"#C#\"\nThis is \"C Sharp\"\nThis is \"C #\"\nThis is \"Crazy\"\n"
そしてテストgsub
:
puts text.gsub(regex, reversed_hash)
どの出力:
This is "#C-Sharp"
This is "#C-Sharp"
This is "#C-Sharp"
This is "#"
さて、私は大きなファイルをメモリに丸呑みするのはあまり好きではありません。今日のマシンには通常、何 GB ものメモリが搭載されていますが、ファイルがまだマシンの RAM を超えていることがあります。File.read
そのため、 を使用してファイルをロードしてからを使用して処理する代わりに、 を使用するgsub
ことをお勧めしFile.foreach
ます。それを使用すると、コードが変更されます。
これが私がそれを行う方法です:
file_to_read = '/path/to/file/to/read'
File.open(file_to_read + '.new', 'w') do |fo|
File.foreach(file_to_read) do |li|
fo.puts li.gsub(regex, reversed_hash)
end
end
File.rename(file_to_read, file_to_read + '.bak')
File.rename(file_to_read + '.new', file_to_read)
これにより、処理された各ファイルの .bak バージョンが作成されるため、何か問題が発生した場合にフォールバックできます。これは常に良い方法です。
編集:CSVファイルを忘れました:
CSVモジュールを使用してRubyで簡単に読み取り/作成できますが、手動で編集したりファイルから生成したりしやすいファイルでハッシュレイアウトを簡単に作成できるため、YAMLファイルを使用します。
編集:CSV、YAML、および一方から他方への生成についての詳細
CSV を読み取り、推奨されるハッシュ形式に変換する方法は次のとおりです。
require 'csv'
text = <<EOT
C#, C-Sharp
C Sharp, C-Sharp
Crazy,
C #, C-Sharp
EOT
hash = Hash.new{ |h,k| h[k] = [] }
special_cases = []
CSV.parse(text) do |k,v|
(
(v.nil? || v.strip.empty?) ? special_cases : hash[v.strip]
) << k.strip
end
前からピックアップ:
reversed_hash = Hash[hash.flat_map{ |k,v| v.map{ |i| [i,k] } }].merge(Hash[special_cases.map { |k| [k, ''] }])
puts reversed_hash
# => {"C#"=>"C-Sharp", "C Sharp"=>"C-Sharp", "C #"=>"C-Sharp", "Crazy"=>""}
CSV ファイルをより編集可能で便利なものに変換するには、上記のコードを使用して と を作成hash
しspecial_cases
、次のようにします。
require 'yaml'
puts ({
'hash' => hash,
'special_cases' => special_cases
}).to_yaml
次のようになります。
---
hash:
C-Sharp:
- C#
- C Sharp
- ! 'C #'
special_cases:
- Crazy
残りは YAML ドキュメントから理解できます。