2012-12-06 52 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”已经浮现在脑海 - 我可能曾经使用过它,所以我不熟悉它。) –

相关问题