2014-05-31 3 views
1

그래서 기본적으로 단어와 구문의 배열이 있습니다. 그들 중 일부는 저주를 포함합니다. 저주에 대한 배열의 각 유닛을 자동으로 스캔하는 메소드를 만들고 싶습니다. 그것이 저주가 없다면, 그것을 새로운 배열에 추가하십시오.objective-c에서 하위 문자열 집합에 대한 문자열 배열을 어떻게 검사합니까?

은 내가 if/else if 제표 및 rangeOfString 방법의 무리와 함께이 작업을 수행 할 수 있습니다 실현,하지만 난 같은 시간에 단어의 무리를 검색합니다 NSString하는 방법을 찾을 수 없어 것을 경악을 금치입니다 .

하위 문자열 배열에 대해 단일 문자열을 검색하는 데 사용할 수있는 기능이 있습니까?

예를 들어

: 내가 좋아하는 문구의 배열이있는 경우 가 :

@[@"hey how are you", 
    @"what is going on?", 
    @"whats up dude?", 
    @"do you want to get chipotle?"] 

을 나는 다음 배열에서 단어 중 하나를 포함하지 않는 새로운 배열을 유도 스캔 할 수 있어야합니다 :

@[@"you", @"hey"] 
+1

매우 기본적인 "check for substrings"기능과 더 멋진 구문을 원하십니까? 그래서 "그들은 바 이유에있다"라고 판단 될 것입니다. 또는 공백 문자를 구분하고 영숫자 만 사용하면 행복할까요? 아니면 NSLinguisticTagger의 모든 기능을 통해 비싸지 만 가능한 정확한 결과를 얻고 싶습니까? – Tommy

답변

1

다소 작은 목록 인 경우 각 단어를 확인하면서 반복합니다.

다소 큰 경우 NSOrderedSet에 "나쁜 단어"를 넣은 다음 방법 : containsObject:을 사용하십시오.

확인할 단어 수가 적지 않은 경우 NSSet에 단어를 넣고 다른 단어는 NSSet에 "나쁜 단어"를 넣고 방법 : intersectsSet:을 사용할 수 있습니다.

예 :
checkWords가에 나쁜 단어를 포함합니다 : 출력

NSArray *stringsToCheck = @[@"hey how are you", @"what is going on?", @"whats up dude?", @"do you want to get chipotle?"]; 
NSSet *badWords = [NSSet setWithArray:@[@"how", @"dude", @"yes"]]; 
for (NSString *line in stringsToCheck) { 
    NSSet *checkWords = [NSSet setWithArray:[line componentsSeparatedByString:@" "]]; 
    NSLog(@"checkWords: %@", checkWords); 

    if ([checkWords intersectsSet:badWords]) { 
     NSLog(@"checkWords contains a bad word in: '%@'", [[checkWords allObjects] componentsJoinedByString:@" "]); 
     // Now search for the specific bad word if necessary. 
    } 
} 

NSLog '어떻게 봐입니다'

+0

"containsObject"메서드를 사용하여 하위 문자열의 문자열을 확인할 수 없습니다. rangeOfString을 사용하여 swear를 반복하면 문자열 중 하나에서 각 swear를 찾을 수 있습니다. –

+0

맞습니다. NSSet과 intersectsSet을 사용합니다. 수정 됨. – zaph

+0

OP 구문은 문자열입니다. intersectsSet을 사용하려면 componentsSeparatedByString을 사용하여 구문을 구문 분석으로 분해하고 해당 배열을 집합으로 변환 한 다음 intersectsSet을 사용해야합니다. 아마도 당신이 검사하고 싶은 각각의 문구에 대해 임시 객체들을 만들어야하기 때문에 아마 좋은 선택이 아닐 것입니다. –

0

나는 두 개의 중첩에 대한-루프를 할 것입니다. 첫 번째 루프는 문구 배열을 스캔하고 두 번째 루프는 단어 배열을 스캔합니다. 세미 의사 코드 (semi-pseudocode)에서 다음과 같이 표현합니다.

NSMutableArray *filtered ... // etc. 
// Loop over each phrase. 
for (NSString *phrase in phrases) { 

    // Let's assume it's acceptable 
    bool good = true; 

    for (NSString *word in words) { 

     // If we find a single unwanted word, we'll no longer take it 
     if ([phrase rangeOfString:word].location != NSNotFound) { 
      good = false; 

      break; // We don't need to keep iterating. 
        // We already know it's not aceptable. 
     } 
    } 

    if (good) [filtered insertObject:phrase]; 

} 
+0

아하! 정말이 고마워요. – shakked

+0

문제 없습니다! 답변을 비교하고 궁극적으로 답을 수락하여 해결 된 것으로 표시하도록하십시오. –

+0

실제로 나는 그것을 구현하고 문제를 발견했습니다 : – shakked

0

다른 접근 방식을 사용합니다.

나는 indexesOfObjectsPassingTest : 메서드를 사용하여 배열을 스캔하고, 맹세가없는 문자열 객체의 인덱스를 반환합니다. 그런 다음 결과 NSIndexSet을 가져 와서 객체를 나열한 새 배열을 만들 때 사용할 수 있습니다 (objectsAtIndexes 메서드 사용). @ kevin9794 말한대로 자신의 코드를 일부 수정이 필요하지만

또한, 2 개 중첩 루프를 사용할 수 있습니다

NSMutableArray *filtered ... // etc. 
// Loop over each phrase. 
for (NSString *phrase in phrases) { 
    BOOL hasSwears = NO; 

    // Loop over each word 

    for (NSString *swear in swears) 
    { 

    // Do the check. This line will be executed once for combination 
    // of items in the arrays. 
    if ([string rangeOfString: swear].location != NSNotFound) 
    { 
     hasSwears = YES; 
     break; 
    } 
    } 
    if (!hasSwears) 
    [filtered insertObject:phrase]; 
} 

정말 옵션과 함께, 당신은 옵션을 지정할 수 있습니다 rangeOfString의 긴 양식을 사용하도록 코드 사건을 비교할 수없는 비교를하는 것.

+0

거의 O (nm)입니다. – zaph

+0

글쎄, 그래. 최악의 경우는 n * m 복잡도입니다. –

0

정직하게 말하자면, 문제의 일부가 쉽게 문제가 될 수밖에없는 임시적인 언 어로 넘어갈 수 있기 때문에 문제가 더 중요하다고 생각합니다. 문장을 단어로 깨는 것은 어렵습니다. 예 :

단어는 종종 다른 단어를 포함합니다. 예를 들어 "they"에는 "hey"가 포함됩니다.하위 문자열 만 검색 할 수는 없습니다.

미국의 인쇄 규칙에 따라 emdash 주위에 공백을 넣지 마십시오. 그래서 정확하게 쓰여진 문장은 "헤이 - 어떻게 지내세요?"입니다. 공백으로 분리하거나 구두점을 제거 할 수 없습니다.

분음 기호는 종종 선택 사항입니다. 미국 영어의 경우조차도 소수의 출판사, 특히 뉴요커의 출판사가 기성복을 사용합니다. 움라우트처럼 보이지만 두 단어가 한 마디로 달리면 두 번째 모음을 표시합니다. coperate처럼. 그러나 일부 언어에서는 단어가 바뀝니다. 독일어의 움라우트는 발음 표이고 예를 들어. Apfel을 Äpfel과 단수로 구분합니다.

그렇다면 Apple을 단순한 API 수준 접근 방식으로 정확히 추가 하시겠습니까? 다른 옵션을 선택하는 모든 사람들은 어떻게해야합니까? 가장 적합한 방법을 구성하는 도구를 제공하는 것이 훨씬 현명합니다.

모든 말했다되는 것을 나는 당신이 설명하고 생각의 산뜻한 가장 컴팩트 한 형태라고 생각합니다 :

NSArray *inputSentences = 
     @[ 
      @"hey how are you", 
      @"what is going on?", 
      @"whats up dude?", 
      @"do you want to get chipotle?" 
     ]; 
    NSArray *forbiddenWords = 
     @[@"you", @"hey"]; 

    NSSet *forbiddenWordsSet = [NSSet setWithArray:forbiddenWords]; 
    NSCharacterSet *nonLetterSet = 
       [[NSCharacterSet letterCharacterSet] invertedSet]; 

    NSPredicate *predicate = 
     [NSPredicate 
      predicateWithBlock: 
       ^BOOL(NSString *evaluatedObject, NSDictionary *bindings) 
       { 
        return ![forbiddenWordsSet intersectsSet: 
          [NSSet setWithArray: 
           [evaluatedObject 
         componentsSeparatedByCharactersInSet:nonLetterSet]]]; 
       }]; 

    NSLog(@"%@", [inputSentences filteredArrayUsingPredicate:predicate]); 

당신이 nonLetterSet 대신 whitespaceCharacterSet 될 수도 있습니다하지만. 너 스스로 판사.

술어는 명시 적 루프 및 수동 누락없이 세트를 자동 필터링하는 데 사용됩니다. 교차 설정은 수동 내부 루프를 피하기 위해 사용됩니다. 약간의 단 정치 못한 비트는 예비 논리를 적용해야하므로 블록 술어를 사용해야합니다.

더하기 측면에서, 대부분의 코드가 설정되었습니다. 하나의 술어를 한 번 작성하여 어 @ 곳에 저장 한 다음 단일 행 호출로 코드의 임의의 h 열 또는 문자열 세트에 적용 할 수 있습니다.

다른 주석 작성자가 언급했듯이 많은 임시 개체가 생성됩니다.

1

당신을 국가로는 다음과 같습니다이 보이지만

내가 동시에

에서 단어의 무리를 검색합니다 NSString하는 방법을 찾을 수 없어 것을 경악 이상한 반응 - 프로그래밍은 결국 솔루션을 구축하는 것입니다. 여기에 하나의 방법을 사용하여 동시에 모든 단어를 검색하지만 NSString 대신 NSRegularExpression에 속하는 솔루션이 있습니다.

우리의 샘플 데이터 :

NSArray *sampleLines = @[@"Hey how are you", 
         @"What is going on?", 
         @"What’s up dude?", 
         @"Do you want to get chipotle?", 
         @"They are the youth" 
         ]; 
NSArray *stopWords = @[@"you", @"hey"]; 

마지막 샘플 라인

우리가 부분적인 단어를 일치하지 않는 확인합니다. 대문자와 소문자가 일치하지 않는지 테스트하기 위해 대문자가 추가되었습니다.단어 경계 옵션이 예
  • (?: ...) 유니 코드 워드 경계를 사용하도록 설정 - - 비 캡처 그룹을 바로 사용

    • \b :

      우리는 중지 단어와 일치하는 RE를 구성 그것은보다 약간 빠른 같은 일을 캡처하고는 전체 경기와 동일합니다 어쨌든

    • | - 또는

    exmaple 정지 단어에 대한 패턴 다음으로

    for (NSString *aLine in sampleLines) 
    { 
        // check for all words anywhere in line in one go 
        NSRange match = [stopRE rangeOfFirstMatchInString:aLine 
                   options:0 
                   range:NSMakeRange(0, aLine.length)]; 
        BOOL containsStopWord = match.location != NSNotFound; 
        NSLog(@"%@: %@", aLine, containsStopWord ? @"Bad" : @"OK"); 
    } 
    

    정규 표현식 매칭을 효율적으로해야하고, : 샘플 라인들이 콘솔에 중지 단어 여부 및 표시 결과를 포함하는 경우 검사를 통해 \b(?:you|hey)\b

    // don't forget to use \\ in a string literal to insert a backslash into the pattern 
    NSString *pattern = [NSString stringWithFormat:@"\\b(?:%@)\\b", [stopWords componentsJoinedByString:@"|"]]; 
    NSError *error = nil; 
    NSRegularExpression *stopRE = [NSRegularExpression regularExpressionWithPattern:pattern 
                         options:(NSRegularExpressionCaseInsensitive | NSRegularExpressionUseUnicodeWordBoundaries) 
                          error:&error]; 
    // always check error returns 
    if (error) 
    { 
        NSLog(@"RE construction failed: %@", error); 
        return; 
    } 
    

    으로 반복 예제에서는 개별 단어를 열거하는 메서드로 많은 임시 개체를 만들어서는 안되며 NSString 개체로 개별 단어 또는 일치 항목을 복사하지 않습니다.

    HTH

  • 관련 문제