2014-02-17 22 views
2

我有一個包含500個字符串(NSString)的數組,每個數字只代表一個字符(例如:@"H"),我將從頭到尾循環。Collection枚舉按順序搜索字符串

在這些字符串有例如字符串如@"H"@"e"@"l"@"l"@"o"

他們是絕對在數組中,但順序是未知的。

我想循環遍歷數組從開始到結束,並想打印出 「你好」,沒有重複。就一次。字符串@"H"必須先發生在「ello」之前。

所以當第一個@"H"發生時,我會開始尋找其餘的「你好」並將它們打印出來。

一直在思考這個過去一小時,我不能只是遺憾的是來什麼:

或許有一些條件,如NSPredicate等在那裏我可以先前發現這些字符串的索引號,以便循環發生。所以我可以將它們打印出來,而不必檢查,因爲我通過陣列循環,從而利用了一堆if-else

例如:

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

而且indexesThatMatchTheStrings將包含匹配索引。如果條件不滿意,那麼我會事先知道我不必將它們打印出來。再次,數組內有「H」,「e」,「l」,「l」,「o」,但順序很重要。

在收藏中是否有這樣的操作?我接受任何種類的收藏和算法(即NSSetNSArray,NSDictionary等)。即使方法在C(位移,結構,內存比較等)。有些東西快速輕量。

附錄:

要概括了一下使用情況:

是否有該框架提供的,使我們可以設置一個測試條件的集合,如任何方式或方法數組,字典或集合,在那裏我們可以根據特定的條件(在我的例子中是hello序列)來查明它們是否真的存在於其中,這樣我們可以最小化循環+比較開銷?或者甚至避免完全循環+搜索的需要,因爲我們知道搜索條件未滿足收集?你的問題的

+0

你可以給你從一個例子輸入要查找的確切輸出的例子嗎?我可以用你的描述來想想幾個場景,只是想得到你想要的。 – Putz1103

+0

讓我們抽象地看問題,所以我們首先找到「H」,然後我們進一步迭代找到「E」,然後再查找字符串的其餘部分。我是否正確理解你的問題? –

+0

@ Putz1103感謝您的回覆。這個數組中有字符,並且「H」,「e」,「l」,「l」,「o」肯定存在(每個字符可以在這個數組中重複,但是順序是未知的)。我想通過在集合中使用一些快速枚舉技術/方法來檢查其中是否存在連續字符「H」「e」「l」「l」「o」。 – Unheilig

回答

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不同的功能(這可能需要相當長的時間比單一循環,因爲我們在整個陣列多次迭代,但蘋果可能已經優化這些功能的位):

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

} 
+0

謝謝+1,我會試試看。 'enumerateUsingBlock'對我來說並不陌生。就我而言,是的,無論如何我需要遍歷整個數組。但是我們也好奇不是,我們可以在一個集合(例如一個數組)上放置一個條件,事先知道某些事實上是否在數組中,這樣循環+比較可以被最小化或者完全避免。 – Unheilig

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!"); 
    } 
+0

+1使用謂詞。將嘗試一下,但我很想知道是否有可能檢查一個數組中的條件(例如,在我的示例中,例如hello字符串序列),而不使用循環,並與使用某些方法進行比較在Objective-C集合中。 – Unheilig

+0

我想過這件事,但似乎不可能,因爲雙「l」。當你將''[NSSet setWithArray:equal]'刪除重複項時,你也將刪除'll' –

+0

如果只有一個'l',那麼可能不使用循環? – Unheilig