从具有最大匹配的另一个字符串中查找字符串模式(存储在数组中)

时间:2014-01-12 02:02:04

标签: ios objective-c regex string

我有以下字符串:

  

“坐下来坐下来吃大吃,然后让CHARLIE PAPA坐下来吃四个跳到空气中的水”#/ p>

我还有一个包含有效字符串结构的数组。这是一个例子

 NSArray *validphrases = @["SIT UP",
                            "SIT UP AND EAT",
                            "CHARLIE",
                            "PAPA",
                            "JUMP IN THE AIR FOR", 
                            "FOUR", 
                            "FIVE",
                            "SECONDS",
                            "JUMP IN THE WATER FOR" nil];

/** And the end result should be these valid phrases detected in order:
 1. Sit up
 2. Sit up and eat
 3. Charlie
 4. Papa
 5. Sit up and eat
 6. Four
 7. Jump in the air for
 8. Five
 9. Seconds */

如果多个字符串在字符串中的给定点匹配,则应返回最长的字符串,然后跳过它。

什么是我能从字符串中找到validPhrases字符串模式的最快方式,省略了不满足validPhrase模式的任何其他单词

这将做的是过滤字符串,取出所有额外的单词,只留下validPhrases并将其放入一个名为preCommands数组的新数组中 我目前的实现是这样的,但应该有一个更简单的方法

  1. 按“”字符分隔的组件拆分字符串。

  2. 迭代组件并查明当前的单词:

    • 在validPhrases数组中作为字符串结构存在:如果是,则将该单词保存到preCOMMANDS数组中。
    • 否则执行另一个数组并继续检查附加到第一个单词的下一个单词,直到该单词集与validPhrases数组中的模式匹配
    • 匹配时,将短语添加到preCOMMANDS数组
  3. 我的这种方法只有当短语在字符串中彼此并排时才有效, 例如

    "SIT UP AND EAT" //will work but
    "SIT SIT UP AND EAT" //will not work if you follow the formula
    

    是否有一个Objective-C方法函数可以用来一次性从字符串中获取所有短语?我觉得我正在重新发明轮子,以确保用其他方法可以做到的事情。

2 个答案:

答案 0 :(得分:2)

NSScanner将为您完成这项工作。您需要遍历输入字符串,随时查找匹配项。你提到应该总是进行最大匹配(“SIT UP AND EAT”优先于“SIT UP”);这只意味着您需要尝试在较短的字符串之前匹配较长的字符串。

扫描仪在源字符串中管理自己的位置。每次匹配时,它都会移动到它的末尾。然而,当它不匹配时,它将不会移动;因此,如果在源中的某个位置,您无法匹配任何目标短语,则必须手动移过该单词。这是通过扫描到下一批分隔字符来完成的 - 在这种情况下,只是空格。

您可能还想查看ParseKit

NSScanner代码会从您的问题中通过测试。

NSArray *validPhrases = @[@"SIT UP",
                          @"SIT UP AND EAT",
                          @"CHARLIE",
                          @"PAPA",
                          @"JUMP IN THE AIR FOR",
                          @"FOUR",
                          @"FIVE",
                          @"SECONDS",
                          @"JUMP IN THE WATER FOR"];

NSSortDescriptor * sD = [[NSSortDescriptor alloc] initWithKey:@"length"
                                                    ascending:NO];
// Order targets by length to get maximal match at any given position.
validPhrases = [validPhrases sortedArrayUsingDescriptors:@[sD]];


NSString * input = @"SIT SIT UP SIT UP AND EAT AND EAT CHARLIE PAPA SIT UP AND EAT FOUR JUMP IN THE AIR FOR WATER FIVE SECONDS";

NSScanner * scanner = [NSScanner scannerWithString:input];

NSMutableArray * foundPhrases = [NSMutableArray array];
NSCharacterSet * whitespace = [NSCharacterSet whitespaceAndNewlineCharacterSet];

while( ![scanner isAtEnd] ){

    NSString * foundPhrase = nil;
    BOOL madeMatch = NO;
    for( NSString * phrase in validPhrases ){

        if( [scanner scanString:phrase intoString:&foundPhrase] ){
            // Got a match; store it and go on to the next position
            [foundPhrases addObject:foundPhrase];
            madeMatch = YES;
            break;
        }
    }

    // No match; step past this word and try the list again
    if( !madeMatch ){
        [scanner scanUpToCharactersFromSet:whitespace intoString:NULL];
        [scanner scanCharactersFromSet:whitespace intoString:NULL];
    }
}

答案 1 :(得分:1)

您可以尝试:

NSArray *filteres = [self.string filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF LIKE %@", givedString]];

你也可以尝试构建不同的谓词,取决于你究竟需要什么,例如:

[NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] %@", givedString]

点击此处查看更多谓词格式: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html