2010-12-06 2 views
2

언어 응용 프로그램을 만들고 있는데, 그 언어와 관련된 어휘 목록이 많습니다 (관심이있는 경우 독일어). 필자는 앱에서 테이블 뷰를 독일어 단어별로 정렬하거나 영어 단어별로 정렬하는 기능을 가지고 있습니다. 배열을 정렬 할 때 특정 문자열을 무시합니다.

나는 다음과 같은 사용

: 절대적으로 완벽하게 작동

NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:type]; 
NSString *string = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; 
NSArray *array = [[string componentsSeparatedByString:@"\n"] sortedArrayUsingSelector:@selector(compare:)]; 

-하는 내 말은, 정확히 예상대로. 그러나 이것에 대해 개선하고 싶은 점은 동사 나 명사와 같은 특정 단어가 있으며, 앞에는 항상 "to"와 같은 접두어가 붙거나 "something"이나 "the"앞에 명사. 그래서 내가하고자하는 것은 어떻게 든 내 정렬에서 이들을 제외 시키는데, 왜냐하면 그렇지 않으면 결국 모든 배열이 매우 익숙하지 않은 내 배열의 "t"섹션 아래에서 알파벳 순으로 정렬되기 때문입니다.

NSString 및 NSArray에 대한 Apple 설명서를 살펴 보았습니다. 여기서는 compare 기능이 (내가 잘못 생각한 경우가 아니라면) 어디서나 볼 수 있으며, 나에게 맞는 방법을 찾지 못했습니다. 이런 식으로 데이터를 처리 한 것은 이번이 처음이므로 무언가 간단하지 않을 수 있습니다. 그래서 도움을 주시면 감사하겠습니다.

정말 감사합니다

Michaeljvdw는

답변

1

당신은 localizedCompare: 또는 localizedStandardCompare:과 약간의 행운이있을 수 있습니다,하지만 난 당신이 원하는 것처럼 이들 중 하나가 기사와 전치사를 제거 것이라고 생각하지 않습니다. 대신, 당신은 아마 찾고있는 당신을 정렬의 특정 스타일을 제공 NSString에 범주를 정의해야합니다 :

@interface NSString (MySortAdditions) 
- (NSComparisonResult)compareWithoutArticles:(NSString *)other; 
@end 

@implementation NSString (MySortAdditions) 
- (NSComparisonResult)compareWithoutArticles:(NSString *)other { 
    NSMutableString *mutableSelf = [NSMutableString stringWithString:self]; 
    [mutableSelf 
     replaceOccurrencesOfString:@"das" 
     withString:@"" 
     options:NSCaseInsensitiveSearch 
     range:NSMakeRange(0, [mutableSelf length]) 
    ]; 

    ... 

    // delete articles from 'other' too 

    NSCharacterSet *trimSet = [NSCharacterSet whitespaceAndNewlineCharacterSet]; 
    NSString *trimmedSelf = [mutableSelf stringByTrimmingCharactersInSet:trimSet]; 
    NSString *trimmedOther = ...; 

    return [trimmedSelf localizedCaseInsensitiveCompare:trimmedOther]; 
} 
@end 

그런 다음 NSArray에 대한 정렬 선택으로 @selector(compareWithoutArticles:)을 사용할 수 있습니다.

+0

이것은 내가 원하는 것처럼 보이지만 replaceOccurrencesOfString을 말할 때 약간 혼동 스럽습니다. @ "das"withString @ ""... 왜냐하면 실제로 "das" (등) 배열에 머물고, 난 그냥 정렬에서 무시해야합니다. 이 코드가 해결할 수 있습니까? 도중에 답해 주셔서 고마워요, 당신의 도움에 감사드립니다. – Michaeljvdw

+0

네, 그 코드가 실제로하는 일은 비교되는 문자열의 복제본을 만든 다음 기사와 공백을 제거하도록 수정합니다. 그것은 말하자면, 문자열을 수정하는 것이 아니라, 성능상의 이유 때문에 두 문자열의 하위 범위를 비교하기 위해 대신'compare : options : range : locale :'을 사용하는 것이 더 바람직 할 수도 있습니다. –

1

먼저 compare:을 사용하지 마십시오. 대신 localizedCompare:을 사용하십시오. 이는 áa 바로 뒤에 나타나는지 또는 z 이후가 언어에 따라 다르므로 중요합니다. localizedCompare:이 처리합니다. 저스틴이 말한대로

localizedStandardCompare:가 사용하는 선택이다,

을 --edit! 나는 그 방법을 몰랐다. 문서에 쓰여 있듯이 localizedStandardCompare:localizedCompare: 이상을 처리하지만 문서는 정확히 무엇을 말하지는 않습니다.

더 원하는 경우 편집

--end, 당신은 자신의 것을 구현해야합니다. 그 목적으로 카테고리을 사용할 수 있습니다. 첫째는

@interface NSString (MichaelsSuperCompareCategory) 
     -(NSComparisonResult)michaelsSuperCompare:(NSString*)string; 
    @end 

하고 기존 클래스에 메소드를 추가 할 수는

@interface NSString (MichaelsSuperCompareCategory) 
     -(NSComparisonResult)michaelsSuperCompare:(NSString*)string{ 
      ... 
     } 
    @end 

이 방법을 구현 선언합니다.그럼 당신은 실수로 애플에 의해 사용되는 내부 방법과 충돌하지 않는 독특한 무언가와 메소드 이름 앞에하는 것이 중요하다

NSArray *array = [[string componentsSeparatedByString:@"\n"] 
           sortedArrayUsingSelector:@selector(michaelsSuperCompare:)]; 

를 사용할 수 있습니다.

기능에 관해서는, 내가 아는 한 스스로 구현해야합니다. [NSLocale currentLocale]으로 현재 로케일을 가져올 수 있습니다. 알고있는 언어에 대해 더 좋은 동작을 구현 한 다음 알 수없는 언어의 경우 기본값은 localizedCompare:입니다.

4

당신은 올바른 길을 가고 있습니다. (내장 된) compare 메서드 대신에 사용하고자하는 메서드는 "to"또는 "the"비트가있을 경우이를 제거 할 수있는 기존 메서드를 작성한 다음 기존 compare 메서드를 사용하는 것입니다. 나는 모든 데이터의 예에 -replaceOccurancesOfStrings을 든 것

// This method can be exposed in a header 
- (NSComparisonResult)myCompare:(NSString*)aString 
{ 
NSString* selfTrimmed = [self removeArticles]; 
NSString* aStringTrimmed = [s2 removeArticles]; 
return [self compare:aString]; 
} 

// This method can be kept private in the .m implementation 
- (NSString*)removeArticles 
{ 
    NSRange range = NSMakeRange(NSNotFound, 0); 
    if ([self hasPrefix:@"to "]) 
    { 
    range = [self rangeOfString:@"to "]; 
    } 
    else if ([self hasPrefix:@"the "]) 
    { 
    range = [self rangeOfString:@"the "]; 
    } 

if (range.location != NSNotFound) 
{ 
    return [self substringFromIndex:range.length]; 
} 
else 
{ 
    return self; 
} 
} 
+0

+1 사용자 정의 비교. 문자열의 시작 부분 이외에 "to"또는 "the"가 표시 될 수 있다고 우려되는 경우 Shaggy의 코드를 사용할 수도 있지만 range.location == 0인지 확인하십시오 (또는 덜 우아한 substringWithRange isEqualToString 것, 문자열 길이를 먼저 확인하십시오. , etc.) –

+0

@Matthew Frederick 좋은 지적. 'hasPrefix'를 사용하는 것으로 바뀌 었습니다. 이것은'rangeOfString'이 기사로 시작하는 경우에만 그것을 찾도록합니다. –

+0

우수한 솔루션입니다. –

0

: 다음과 같은 방법으로 NSString에게주는 사용자 정의 범주를 사용

NSArray *array = [[string componentsSeparatedByString:@"\n"] sortedArrayUsingSelector:@selector(myCompare:)]; 

:

귀하의 호출은 다음과 같을 것 "To"-> ""- 그런 다음 데이터를 다시로드하십시오. (또는이 텍스트 편집기에서 수 있습니다)

예를 들어, 'walk to'을 'walk (to)'로 변경하는 것을 고려해야합니다. 이는 미리 수행 할 수 있으며 (또한 사용자에게 혼란을 덜어줍니다 그들이 알파벳순으로 스크롤하고 있기 때문에).