2012-11-13 2 views
12

문자열이 있으면 해당 문자열에 나타나는 각 단어의 수를 가져와야합니다. 그렇게하기 위해, 나는 문자열로 문자열을 문자열로 추출하고 그런 식으로 검색했지만, 문자열을 직접 검색하는 것이 더 최적이라고 생각했습니다. 아래는 내가 원래 문제를 해결하기 위해 작성한 코드입니다. 그래도 더 나은 솔루션에 대한 제안을하고 있습니다.iOS - 문자열에서 단어 발생 횟수를 찾는 가장 효율적인 방법

NSMutableDictionary *sets = [[NSMutableDictionary alloc] init]; 

NSString *paragraph = [[NSString alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"text" ofType:@"txt"] encoding:NSUTF8StringEncoding error:NULL]; 

NSMutableArray *words = [[[paragraph lowercaseString] componentsSeparatedByString:@" "] mutableCopy]; 

while (words.count) { 
    NSMutableIndexSet *indexSet = [[NSMutableIndexSet alloc] init]; 
    NSString *search = [words objectAtIndex:0]; 
    for (unsigned i = 0; i < words.count; i++) { 
     if ([[words objectAtIndex:i] isEqualToString:search]) { 
      [indexSet addIndex:i]; 
     } 
    } 
    [sets setObject:[NSNumber numberWithInt:indexSet.count] forKey:search]; 
    [words removeObjectsAtIndexes:indexSet]; 
} 

NSLog(@"%@", sets); 

예 :

시작 문자열 :
"..이 이것은 단지 테스트 테스트입니다"

결과 :

  • "이것은"- 2
  • "A"- - 2
  • "테스트"- 2
  • "전용"2
  • "입니다"- 1
+0

방법은 작동합니까? 도트 기호에 문제가 있습니까? 나는 당신이 "시험"을해야한다고 생각합니다. "테스트"보다는. – Ricardo

답변

23

이것은 정확히 NSCountedSet의 용도입니다.

문자열을 따로 분리해야합니다 (iOS는 구두점을 걱정할 필요가 없도록 충분히 유용합니다). 그리고 각각을 카운트 된 세트에 추가하십시오. 각 개체가 집합에 나타나는 횟수의 트랙 :

NSString  *string  = @"This is a test. This is only a test."; 
NSCountedSet *countedSet = [NSCountedSet new]; 

[string enumerateSubstringsInRange:NSMakeRange(0, [string length]) 
          options:NSStringEnumerationByWords | NSStringEnumerationLocalized 
         usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop){ 

          // This block is called once for each word in the string. 
          [countedSet addObject:substring]; 

          // If you want to ignore case, so that "this" and "This" 
          // are counted the same, use this line instead to convert 
          // each word to lowercase first: 
          // [countedSet addObject:[substring lowercaseString]]; 
         }]; 

NSLog(@"%@", countedSet); 

// Results: 2012-11-13 14:01:10.567 Testing App[35767:fb03] 
// <NSCountedSet: 0x885df70> (a [2], only [1], test [2], This [2], is [2]) 
+0

OMG!상상할 수있는 것보다 훨씬 쉽습니다! 고맙습니다! – RyJ

+0

당신을 진심으로 환영합니다! – lnafziger

+0

@Inafzinger하지만 약간의 문제가 있습니다. 일부 HTML 태그가 포함 된 NSString의 단어 개수를 계산할 때 건너 뛸 수 있습니다. 그러나 나는 그것들을 세고 싶다. 이것에 대한 어떤 생각. –

2

내가 추측해야한다면, 나는 그것에 대해 NSRegularExpression라고 말할 것입니다. 이와 같이 :

NSUInteger numberOfMatches = [regex numberOfMatchesInString:string 
                options:0 
                 range:NSMakeRange(0, [string length])]; 

해당 스 니펫은 here에서 가져 왔습니다.


편집 1.0 : 어떤 선생님을 바탕으로

말했다까지 :

  • 문장 부호 :

    NSString *string = @"This is a test, so it is a test"; 
    
    NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; 
    NSArray *arrayOfWords = [string componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; 
    for (NSString *word in arrayOfWords) 
    { 
        if ([dictionary objectForKey:word]) 
        { 
         NSNumber *numberOfOccurences = [dictionary objectForKey:word]; 
         NSNumber *increment = [NSNumber numberWithInt:(1 + [numberOfOccurences intValue])]; 
         [dictionary setValue:increment forKey:word]; 
        } 
        else 
        { 
         [dictionary setValue:[NSNumber numberWithInt:1] forKey:word]; 
        } 
    } 
    

    당신은 조심해야한다. (가까운 단어 근처)

  • 어퍼 케이스 단어 대 lowerCase 단어.
+0

각 단어의 수가 필요합니다. 문자열에서 "이것은 테스트입니다. 이것은 테스트 일뿐입니다." "test"는 2, "this"는 2, "only"는 1 등이됩니다. – RyJ

+0

내 편집을 확인하십시오 .. – Peres

1

나는 루프가있는 긴 단락 중에서 단어를 검색하려고한다는 것은 매우 나쁜 생각이라고 생각합니다. 정규 표현식을 사용해야합니다. 처음에는 배우는 것이 쉽지 않지만 알아두면 좋습니다! 이 경우 살펴보기 Use regular expression to find/replace substring in NSString

관련 문제