集合枚举按顺序搜索字符串

时间:2014-02-17 19:05:18

标签: ios objective-c c collections nspredicate

我有一个包含500个字符串(NSString)的数组,每个字符串只代表一个字符(例如:@"H"),我将从头到尾循环。

在这些字符串中,例如@"H"@"e"@"l"@"l"@"o"等字符串。

数组中的 肯定是 ,但订单未知。

我想从头到尾遍历数组,并希望打印出来 "你好"没有重复。就一次。字符串@"H"必须先出现在" ello"。

之前

所以当第一个@"H"出现时,我会开始寻找其余的,即" ello"并打印出来。

在过去的一个小时里一直在考虑这个问题,除了:

之外我无法做任何事情

也许有一些条件如NSPredicate等我可以在循环发生之前先按顺序查找这些字符串的索引号。所以我可以打印出来,而不必检查,因为我循环遍历数组,从而使用一堆if-else

例如:

NSArray *indexesThatMatchTheStrings = [......(condition => @"H", @"e", @"l", @"l", @"o").....]'

indexesThatMatchTheStrings将包含匹配的索引。如果条件不满意,那么我事先就知道我不打算将它们打印出来。再次," H"," e"," l"," l"," o"在数组中,但顺序很重要。

集合中是否有这样的操作?我对任何类型的集合和算法都很开放(即NSSetNSArrayNSDictionary等等。甚至C中的方法(位移,结构,内存比较等)。有些东西速度快,重量轻。

附录:

概括一下用例:

框架是否提供了任何方法或方法,我们可以使用这些方法或方法为集合(例如数组,字典或集合)设置测试条件,我们可以根据这些方法或方法确定某些事物是否在其中一个特定的条件(在我的例子中:hello序列),以便我们可以最小化循环+比较开销?或者甚至完全不需要循环+搜索,因为我们知道集合的搜索条件不满足?

2 个答案:

答案 0 :(得分:2)

这是我的版本:

NSArray * allChars = @[@"l", @"A", @"B", @"H", @"b", @"e", @"H", @"c", @"c", @"l", @"b", @"q", @"l", @"l", @"l", @"z", @"o", @"H", @"e", @"l",@"l", @"o", @"l"];
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"SELF in[cd] %@", @[@"H", @"e", @"l", @"o"]];
NSArray * equal = [allChars filteredArrayUsingPredicate:predicate];
NSString * sayHello = @"";

// This loop will find any sequence of Hello's characters

for (int i=0; i<equal.count; i++)
{
    NSString * nextChar = equal[i];
    NSString * try = [sayHello stringByAppendingString:nextChar];

    if ([@"Hello" rangeOfString:try].location == 0) {
        sayHello = try;
    }

    if ([sayHello rangeOfString:@"Hello"].location != NSNotFound) {
        NSLog(@"Hello!");
        break;
    }
}

// This loop works if between Hello's char cannot be any other characters

sayHello = @"";

for (int i=0; i<equal.count; i++)
{
    sayHello = [sayHello stringByAppendingString:equal[i]];
    if ([sayHello rangeOfString:@"Hello"].location != NSNotFound) {
        NSLog(@"Hello!");
        break;
    }
}

return YES;

编辑:感谢编写正则表达式的@melvas's,我使用NSRegularExpression并且没有循环:

    NSString * possibleHello = [equal componentsJoinedByString:@""];    
    NSString * regex = @"(?=(h|H))(.*?)(?=(e|E))(.*?)(?<=(l|L))(.*?)(?=(l|L))(.*?)(?=(o|O))";

    NSError * error = nil;        
    NSRegularExpression * regularExp = [NSRegularExpression regularExpressionWithPattern:regex
                                                                                 options:NSRegularExpressionDotMatchesLineSeparators
                                                                                   error:&error];
    NSArray * matches = [regularExp matchesInString:possibleHello
                                            options:NSMatchingReportProgress
                                              range:NSMakeRange(0, posibleHello.length)];
    if (matches.count) {
        NSLog(@"Hello!");
    }

答案 1 :(得分:1)

根据我对你的问题的解释,首先回答你的问题(假设你正在循环遍历你的阵列):

你知道你在寻找什么字符,以及你正在寻找它们的顺序(我假设)。因此,创建所需对象的数组以及所需的确切顺序。然后遍历数据数组并根据已知数组和该数组中的当前位置检查每个对象。然后打印,保存,删除任何信息。

NSArray *knownArray = [NSArray arrayWithObjects:@"H", @"e", @"l", @"l", @"o", nil];
int currentLocationInKnownArray = 0;
for(int i = 0; i < [data count]; i++)
{
    if([[data objectAtIndex:i] isEqualToString:[knownArray objectAtIndex:currentLocationInKnownArray]])
    {
        //You found a match
        currentLocationInKnownArray++;

        //Do whatever else you would like with the index or data from this loop.
    }
}

//Now check if you found your complete set
if(currentLocationInKnownArray == [knownArray count])
{
    //You found them all in order in your array.
}

如果你不打算迭代你的数组,那么你可以在NSArray中使用不同的函数(这可能比单个循环花费更长的时间,因为我们遍历整个数组多次,但Apple可能已经优化这些功能有点):

NSArray *knownArray = [NSArray arrayWithObjects:@"H", @"e", @"l", @"l", @"o", nil];

__block int currentIndexInMaster = 0;
for(int i = 0; i < [knownArray count]; i++)
{
    __block bool validObjectFound = false;
    NSIndexSet *set = [data indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
        if([(NSString*)obj isEqualToString:[knownArray objectAtIndex:i]])
        {
            return true;
        }
        return false;
    }];

    [set enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
        //... do something with idx
        // *stop = YES; to stop iteration early
        if(idx > currentIndexInMaster)
        {
            currentIndexInMaster = idx;
            validObjectFound = true;
            *stop = TRUE;
        }
    }];

    if(!validObjectFound)
    {
        //No longer valid data, do not continue
        break;
    }

}