번역 표와 같이 해시로 시작하는 것이 좋습니다. 해시 조회는 매우 빠르며 태그와 그 대체물을 멋지게 정리할 수 있습니다.
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'
은 특이하다,하지만 우리가 다룰 것입니다 그.
루비의 String.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'
에 추가
은 "특별한 경우"의 두 번째 해시를 병합하여, 쉽게 :
정규식 buildin '코드가 사용
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 버전을 생성합니다, 그래서 뭔가 잘못되면 당신은 항상 좋습니다 가을 백을 가지고 : 여기
내가 그것을 할 거라고 방법입니다.
편집 : 그것은 당신이 쉽게 만들 수 있기 때문에 그러나 나는 YAML 파일과 함께 가고 싶어,
당신은 읽기/루비는 CSV 모듈을 사용하여 쉽게 만들 수 있습니다 : 나는 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
전에에서 따기 : CSV, YAML에 대한 자세한 다른
에서 하나를 생성하는 여기에 CSV를 읽고 권장 해시 형식으로 변환하는 방법 :
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 파일을 더 편집 가능하고 유용한 것으로 변환하려면 ab 비켜 코드는, 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 워드 프로세서에서 알아낼 수 있습니다.
'# gsub'에 대한 두 번째 인수로 멋진 트릭입니다. 'reversed_hash'를 얻기 위해'Hash # invert'를 사용할 수 있습니까? '{1 => : a, 2 => : b} .invert # => {: a => 1, : b => 2}'. –
'invert'는 간단한 'key'=> 'value' '조합으로 해시를 처리하지만이 해시에는 값 배열이 있습니다. 루비에서는 배열을 키로 허용하지만 해시는 키에 대한 객체를 허용하기 때문에 코드는 값의 각 요소를 자체 키로 변환해야합니다. –