2011-11-07 3 views
4

Java에서 정규화/비 악센트 텍스트를 어떻게 만들 수 있습니까? 현재 java.text.Normalizer를 사용 중입니다.Java에서 텍스트 정규화/해제 중

Normalizer.normalize(str, Normalizer.Form.NFD) 
    .replaceAll("\\p{InCombiningDiacriticalMarks}+", "") 

그러나 완벽하지는 않습니다. 예를 들어 노르웨이어 문자 æ 및 ø은 그대로 둡니다. 누구든지 대안을 알고 있습니까? 저는 모든 종류의 언어로 된 문자를 a-z 범위로 변환 할 수있는 무언가를 찾고 있습니다. 이를 수행 할 수있는 여러 가지 방법이 있다는 것을 알고 있습니다 (예 : 'a', 'e'또는 'ae'로 인코딩해야합니까?) 어떤 해결책 으로든 열려 있습니다. 나는 내가 모든 언어에 대해 이것을 잘 수행 할 수 없을 것이라고 생각하기 때문에 나 자신을 쓰지 않는 것을 선호한다. 성과는 중요하지 않습니다.

사례 : 사용자 입력 이름을 일반 a-z 원거리 이름으로 변환하고 싶습니다. 변환 된 이름이 사용자에게 표시되므로 가능한 한 사용자가 원래 언어로 작성한 것과 최대한 일치 시키길 원합니다.

편집 :

좋아 명, 야호, 내 질문에 주소 게시물을 negging하지 주셔서 감사합니다! :) 유스 케이스를 버려야 할 수도 있습니다. 그러나 명확하게 해주십시오. 이름을 내부적으로 저장하려면 이름을 변환해야합니다. 나는 여기에 허용 된 글자의 선택을 통제하지 못한다. 이름은 예를 들어 URL에서 사용자에게 표시됩니다. 이 포럼의 사용자 이름이 정규화되고 이름을 클릭하면 URL에 표시되는 것과 같은 방식입니다. 이 포럼은 "Băşan"과 같은 이름을 "baan"으로, "Øyvind"와 같은 이름을 "yvind"로 변환합니다. 나는 그것이 더 잘할 수 있다고 믿습니다. 나는 나를 위해 이것을하기 위해 아이디어와 선호하는 도서관 기능을 찾고있다. 나는 "O"와 "ø"가 다르다는 것을 알고 있지만, 내 이름이 "Øyvind"이고 온라인 포럼에 등록하면 내 사용자 이름이 " ovind "가 아니라"yvind "가됩니다. 이것이 어떤 의미가되기를 바랍니다! 감사!

(그리고 NO, 우리는 사용자가 자신의 사용자 이름을 선택 할 수 없습니다. 나는 정말 java.text.Normalizer. 감사에 대한 대안을 찾고 있어요!)

+3

많은 언어 (예 : 노르웨이어)는 라틴어 a-z 범위와 다른 * 문자를 사용합니다. ø는 슬래시가있는 슬래시가 아닙니다 (슬래시는 선택 사항이 아닙니다). 맹 글링 된 버전 대신 사용자에게 적절한 이름을 보여 주시겠습니까? –

+3

모든 이름을 a-z로 변환 할 수 없습니다. Annabel-Sue는 하이픈을 가지고 있기 때문에 변환 할 수 없습니다. 키릴 어, 그리스어, 페르소 아라비아어와 같은 다른 알파벳의 이름은 쉽게 로마 알파벳으로 변환 할 수 없습니다. 나는 왜 당신이 이것을하려고 노력하는지 모르지만 사람들의 이름에 구조를 부여하는 것은 일을하는 올바른 방법입니다. –

+0

고마워요.하지만 텍스트를 정규화해야하는지 아닌지에 대한 논의가 아니길 바랬습니다. 가능하면 저장하고 사용자에게 원래 이름을 표시하지만 일부 상황에서는 정규화 된 버전이 계속 표시됩니다. 이 사이트는 똑같습니다. stackoverflow 이름이 "Băşan"이면 사용자 이름은 "baan"이됩니다. 이 이름은 귀하와 귀하의 프로필을 통해 다른 사람에게 보입니다. 나는 루마니아 인에 익숙하지 않지만 "basan"이 더 나은 음역이었을 것이라고 추측 할 수 있습니까? 하이픈, 아포스트로피 등은 아마도 그냥 가야 할 것입니다. 나는 이것을 위해 도구를 찾고있다. – John

답변

2

당신이 모두를 고려하고있는 가정 당신이하고있는 일의 의미, 그것이 잘못 될 수있는 모든 방법, 라틴 알파벳에 동등한 의미가없는 중국 그림과 다른 것들을 얻을 때 무엇을 할 것인가 ...

나는 그게 네가 원하는 걸하는 거지. 만약 당신이 동등성의 목록을 가지고 있다면 ('æ'에서 'ae'또는 무엇이든), 파일에 저장할 수 있습니다 (또는 메모리에서 정렬 된 배열로 이것을 많이 수행한다면, 성능상의 이유로) 조회 한 후 문자로 교체하십시오. char 배열로 (# of unicode characters)를 저장하는 메모리 공간이 있다면 각 문자의 유니 코드 값을 통해 실행할 수 있고 직선적 인 조회가 가장 효율적입니다.

즉/u1234 => lookupArray [1234] => 'Q'

이든. 나는 처음부터, 그래서 아마 나쁜 메서드 호출 또는 무언가가 있음을 썼다

StringBuffer buf = new StringBuffer(); 
for (int i = 0; i < string.length(); i++) { 
    buf.append(lookupArray[Character.unicodeValue(string.charAt(i))]); 
} 

:

그래서 당신과 같은 루프를해야합니다.

아마도 미리보기 버퍼를 사용하여 분해 된 문자를 처리해야합니다.

행운을 빌어 요 - 이것은 함정이 가득한 것이라고 확신합니다.

+0

지도를 사용하고 string.replace (...)를 수행 할 수도 있습니다. 모두와 마찬가지로, 내가 항상 알려지지 않은 요소 (예기치 않은 문자)가 있기 때문에 그러한 교체가 약간 걱정됩니다. – aishwarya

+0

map/string.replace는 내가 생각한 첫 번째 것이었지만, 성능상의 이유로 나는 훨씬 더 느릴 것이라고 생각했다. String.replace()는 문자열의 크기에서 O (N)이 될 것이고,지도 조회는 큰 O가 무엇이든간에 (naively, 나는 그것이 O (M)이라고 생각합니다. 지도). 배열 조회를 수행하는 것은 O (1)이며 문자열 버퍼를 작성하는 것은 O (1)입니다. 따라서 긴 문자열에서 * 훨씬 * 빠르며 모든 유니 코드 문자를 처리하는 데 필요한 엄청나게 큰 매핑이됩니다. – Kane

+0

질문에 초점을 맞춰 주신 것에 감사드립니다! 그래, 나는 당신의 접근 방식을 고려했고, 나는 그것이 일을하는 가장 효율적인 방법이라고 생각한다. 내가 나의 OP와 다른 사람들도 언급했듯이 나는 분명히 일들을 놓치거나 내가 익숙하지 않은 언어로 잘못 음역 할 것이므로이 접근법을 사용하는 것에별로 신경 쓰지 않는다. 내가 더 나은 길을 찾지 못한다면, 결국 내가 끝낼 수도 있습니다. – John