2009-09-03 3 views
14

I는 다음 내용을 실행할 경우string.Compare가 악센트 부호가있는 문자를 일관성 없게 처리하는 이유는 무엇입니까?

string.Compare("mun", "mün", true, CultureInfo.InvariantCulture) 

결과는 '-1', 'MUN가'MUN '보다 낮은 수치를 갖는 것을 나타낸다. 나는이 문장 실행하면

그러나 :

string.Compare("Muntelier, Schweiz", "München, Deutschland", true, CultureInfo.InvariantCulture) 

내가 할 '를 Muntelier, Schewiz은'마지막가는 것을 나타내는, '1'.

비교에 버그입니까? 또는, 가능성,


이이 문제가되는 이유는

을 강조 포함하는 문자열을 정렬 할 때 나는 고려되어야 할 규칙은, 내가 목록을 정렬하고 의미있어 수동 바이너리 필터를하고있어이 'xxx'로 시작하는 모든 문자열을 가져옵니다.

이전에 Linq 'Where'방법을 사용했지만 다른 사람이 작성한이 사용자 지정 함수를 사용해야합니다. 왜냐하면 더 나은 성능을 발휘하기 때문입니다.

그러나 사용자 지정 함수는 .NET에있는 '유니 코드'규칙을 고려하지 않습니다. 'mun'으로 시작하는 목록에 항목이 있어도 'mun'으로 필터링하도록 말하면 항목을 찾지 못합니다.

이것은 악센트 부호가있는 문자 다음에 오는 문자에 따라 악센트 부호가있는 문자의 순서가 일치하지 않기 때문인 것으로 보입니다.


그래, 문제가 해결 된 것 같습니다.

필터 전에, 나는 N 검색 문자열의 길이 각 문자열의 첫 번째 N 문자를 기반으로 정렬을한다.

+0

그것은 내가 .NET Framework를 원하는 그 같은 순간의 비교 때문에 같은 (손실 언어로 "U"에 "U"equivelent)입니다 오픈 소스 였기 때문에 디버그 모드로 들어가서 정확히 무엇을하고 있는지 파악할 수있었습니다. – Jonathan

+4

@jonathanconway : 기본 클래스 라이브러리의 소스 코드를 단계별 것이 가능하고, 볼 http://blogs.msdn.com/sburke/archive/2008/01/16/configuring-visual-studio-to-debug-net- framework-source-code.aspx –

+0

@divo 참고로 감사드립니다. 이것이 가능하다는 것을 결코 깨닫지 못했습니다! – Jonathan

답변

22

직장에서 계층 구분 알고리즘이, http://unicode.org/reports/tr10/

이 언어에 민감한 정렬의 복잡성을 해결하기 위해 참조 다단계 비교 알고리즘이 이용 이다. 예를 들어, 두 단어를 비교할 때, 가장 중요한 기능은 기본 문자 입니다 : 그런는 A와 B. 악센트 차이 사이의 차이로 기본 문자의 차이 이있는 경우 이 무시 일반적이다. 기본 또는 액센트의 차이가 인 경우 대소 문자 차이 (대문자 대 소문자)은 일반적으로 무시되는 입니다. 구두점이 가변적입니다. 어떤 상황에서 구두점 문자는 기본 문자처럼 취급되는 입니다. 다른 상황에서는 기본, 액센트 또는 대소 문자가있는 경우 은 무시해야합니다. 차이점. 또한 최종 타이 브레이크 수준, 경우 문자열의 모든 에서 다른 차이가 없습니다 이에는 (정규화) 코드 포인트 위해 사용이있을 수 있습니다.

그래서 "Munt ..."및 "Münc ..."은 알파벳 순서가 다르며 "t"및 "c"를 기준으로 정렬됩니다.

는 "MUN"와 "MUN"반면 알파벳 문자 코드가

6

악센트 부호가있는 문자가 일종의 "tie-break"상황 (즉, 문자열이 다른 경우)에서만 사용되는 것처럼 보입니다. 여기

는 입증하기 위해 몇 가지 예제 코드입니다 : (. 나는 "N"뿐만 아니라 뒤에 공백을 추가하는 시도했습니다, 그것은 단어 경계에 수행 된 경우 확인 - 그렇지 않은)
using System; 
using System.Globalization; 

class Test 
{ 
    static void Main() 
    { 
     Compare("mun", "mün"); 
     Compare("muna", "münb"); 
     Compare("munb", "müna"); 
    } 

    static void Compare(string x, string y) 
    { 
     int result = string.Compare(x, y, true, 
            CultureInfo.InvariantCulture)); 

     Console.WriteLine("{0}; {1}; {2}", x, y, result); 
    } 
} 

결과 :

mun; mün; -1 
muna; münb; -1 
munb; müna; 1 

나는이 여러 가지 복잡한 유니 코드 규칙에 의해 올바른 의심 -하지만 난 그들에 대해 충분히 알지 못한다.

당신이 이것을 고려해야하는지에 관해서는 ... 나는 그렇게 기대하지 않을 것입니다. 이것으로 인해 당신은 무엇을하고 있습니까?

4

나는 이것을 이해하지만 여전히 다소 일관성이있다. CultureInfo.InvariantCulture을 사용하여 비교할 때 움라우트 문자 ü은 액센트가없는 문자 u처럼 처리됩니다.

첫 번째 예제의 문자열이 분명히 같지 않으므로 결과는 0이 아닌 -1 (기본값 인 것처럼 보임)입니다. 두 번째 예에서는 Munteliert이 알파벳 뒤에 c 뒤에 오는 것이므로 마지막으로 적용됩니다.

나는이 규칙을 설명하는 MSDN에서 명확한 문서를 찾을 수 없습니다,하지만 난

string.Compare("mun", "mün", CultureInfo.InvariantCulture, 
    CompareOptions.StringSort); 

string.Compare("Muntelier, Schweiz", "München, Deutschland", 
    CultureInfo.InvariantCulture, CompareOptions.StringSort); 

원하는 결과를 얻을 것을 발견했다.

어쨌든, 가능한 한 현재 사용자의 문화권과 같은 특정 문화권에 기반하여 정렬하는 것이 더 나을 것이라고 생각합니다.

+0

'CompareOptions.Ordinal'도 옵션이 될 수 있습니다. 이 옵션을 사용하면 문자열이 유니 코드 값에 따라 비교됩니다. http://msdn.microsoft.com/en-us/library/system.globalization.compareoptions.aspx를 참조하십시오. –