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



我有一个包含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中的偶数方法(移位、结构、内存比较等)。有些东西又快又轻。

附录:

概括一下用例:

该框架是否提供了任何方法或方法,我们可以为数组、字典或集合等集合设置测试条件,在那里我们可以根据特定条件(在我的例子中是:h e l l o序列)来确定某些东西是否真的在其中,这样我们就可以最大限度地减少循环+比较开销?或者甚至完全避免循环+搜索的需要,因为我们知道集合的搜索条件不满足?

这是我的版本:

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;

EDIT:多亏@melvas编写了正则表达式,我用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!");
}

根据我对您的问题的解释,第一次回答您的问题(假设您无论如何都在数组中循环):

你知道你在寻找什么角色,以及你在寻找他们的顺序(我假设)。所以,创建一个您想要的对象数组和您想要的确切顺序。然后循环遍历数据数组,并根据已知数组和该数组中的当前位置检查每个对象。然后用那里的信息打印、保存、浏览任何内容。

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中使用不同的函数(这可能需要比单个循环更长的时间,因为我们多次迭代整个数组,但苹果可能已经优化了这些函数):

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;
}
}

最新更新