2012-12-06 53 views
0

我有一個NSArrayStore對象。每個Store對象有兩個NSString對象; StoreIDName。 我想快速檢查這個NSArray中是否存在Store對象的ID。檢查NSArray中的自定義對象是否存在NSString

例子:

Store *s1 = [[Store alloc] init]; 
s1.name = @"Some Name"; 
s1.id = @"123ABC"; 

Store *s2 = [[Store alloc] init]; 
s2.name = @"Some Other Name"; 
s2.id = @"ABC123"; 

NSArray *array = [[NSArray alloc] initWithObjects:s1, s2, nil]; 

NSString *myIdOne = @"ABCDEF"; 
NSString *myIdTwo = @"123ABC"; 

BOOL myIdOneExists = ...? 
BOOL myIdTwoExists = ...? 

...?我需要搞清楚。我知道我可以使用for循環來做到這一點,並發現時...但在我看來,這似乎是一個討厭的方法,因爲NSArray可能包含數千個對象,......理論上。
所以我想知道更好的解決方案。

+0

這怎麼幫我? –

+0

您是否認爲該系統有一些神奇的方式來查看數組條目,而不必一次只進行一次? –

+0

@Pfitz - 我不知道BOOL是一個對象。 –

回答

2

試試這個:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %@",@"id", myID]; 
NSArray *filteredArray = [array filteredArrayUsingPredicate:predicate]; 
if (filteredArray.count > 0) 
    Store *store = [filteredArray objectAtIndex:0]; 
+0

當然,該方案將迭代所有的數組元素,即使在第二個中找到了「答案」。 –

+0

當然,您可以使用快速枚舉,自己進行搜索,並在找到您正在搜索的商店時停止搜索,但如果數組足夠小,則此解決方案應該執行此操作。 – tilo

+0

謝謝。我的猜測是陣列至多會包含大約200個物體......你還會建議你的解決方案嗎? –

1

簡單的解決方案,只需使用KVC:

NSArray *results = [array valueForKey:@"id"]; 
BOOL myIdOneExists = [results containsObject:myIdOne]; 
BOOL myIdTwoExists = [results containsObject:myIdTwo]; 
+0

因此,您將構建一個包含所有萬個ID的數組,以查看它們中的一個是否匹配? –

+0

這是一個好主意,不過像@HotLicks暗示,如果數組大小爲10k個對象,它會創建大量內存使用量。 –

+0

@HotLicks不,他會創建一個包含*引用*到所有萬個ID的數組。 (也許這不會小得多,但仍然...) – trudyscousin

1
-(BOOL) id:(NSString*) theId existsInArray:(NSArray*) theArray { 
    for (Store* theStore in theArray) { 
     if ([theStore.id isEqualToString theId]) { 
      return YES; 
     } 
    } 
    return NO; 
} 

另一種方法是實現StoreisEqual方法僅對比的ID。然後使用您正在查找的ID構建虛擬Store對象,並使用indexOfObjectcontainsObject,引用您的虛擬Store對象。

+0

我引用這個問題:'我知道我可以使用for循環來做到這一點,並在發現時中斷。在你的回答中唯一遺漏的是'break;'不循環不必要。不過謝謝。 –

+0

@PaulPeelen - 由於它從循環中返回,因此不需要中斷。 –

+0

爲真。沒有想到這一點。 –

4

以下是事情:無論您使用哪種解決方案,它都會或多或少地歸結爲「遍歷數組並返回是否找到該對象。」除非滿足特定的條件(例如,數組已經按您搜索的值排序),否則無法更快地搜索數組。您可以使用謂詞,可以使用枚舉器,可以使用快速枚舉或者可以使用測試塊 - 在引擎蓋下,它們都是「遍歷數組並執行測試」。這就是陣列的工作原理。

如果這是您需要經常做的事情,並且性能是天真解決方案的問題,那麼一個合理的解決方案可能是將您的ID緩存在NSSet中。集合被調整用於快速成員檢測,所以你應該能夠比使用數組更快地得到答案。

我個人的 「環以上的非陣列」 的解決方案:

BOOL idExists = NSNotFound != [stores indexOfObjectPassingTest:^(Store *store, NSUInteger idx, BOOL *stop) { 
    return [store.id isEqualToString:@"whatever"]; 
}]; 

(寫在瀏覽器中,所以,你知道,告誡compilor。)

+0

+1。這是非常乾淨整潔。 – iDev

+0

是的,你提出了比我更好的觀點,無論如何,你正在迭代所有元素。雙重目標應該是有效地做到這一點(只有一次,並且只需最少的附加對象創建),並以「明顯」的方式做到這一點,這種方式足夠「明顯」可以維護,不太可能含有微妙的錯誤。 (我希望「indexOfObjectPassingTest」已經浮現在腦海 - 我可能曾經使用過它,所以我不熟悉它。) –

相關問題