NSArray具有查找指定索引的对象的有用方法
// To find objects by indexes
- (id)objectAtIndex:(NSUInteger)index
- (NSArray *)objectsAtIndexes:(NSIndexSet *)indexes
// To find index by object
- (NSUInteger)indexOfObject:(id)anObject
但是,我希望获得给定对象的NSIndexSet
(多个索引)。类似的东西:
- (NSIndexSet *)indexesOfObjects:(NSArray *)objects
NSArray
不存在此方法。我错过了什么吗?有人知道另一种标准方法吗?否则我必须将其写为类别方法。
答案 0 :(得分:13)
较新的NSArray版本(OSX 10.6和iOS 4)提供indexesOfObjectsPassingTest:
方法。
NSIndexSet *indexesOfObjects = [[array1 indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
return [array2 containsObject:obj];
}];
答案 1 :(得分:6)
使用set来指定要查找的对象可能很有用,例如:
- (NSIndexSet *) indicesOfObjectsInSet: (NSSet *) set
{
if ( [set count] == 0 )
return ( [NSIndexSet indexSet] );
NSMutableIndexSet * indices = [NSMutableIndexSet indexSet];
NSUInteger index = 0;
for ( id obj in self )
{
if ( [set containsObject: obj] )
[indices addIndex: index];
index++;
}
return ( [[indices copy] autorelease] );
}
这需要访问数组中的每个对象,但至少只执行一次,并在执行此操作时使用快速枚举。使用NSSet并针对该集测试数组中的每个对象也比测试包含在数组中要快得多。
这里有一个潜在的优化,但是在单个对象多次存储在接收数组中的情况下它会破裂:
if ( [set containsObject: obj] )
{
[indices addIndex: index];
if ( [indices count] == [set count] )
break;
}
这样一来,如果你为两个物体扫描一个20'000项目的阵列并且它们都在前十个内,你将能够避免扫描阵列中的其他19'990个物体。正如我所说的那样,如果数组包含重复项,则无效,因为只要找到2个索引就会停止(即使它们都指向同一个对象)。
说完后,我同意迈克上面的评论。你有可能让自己陷入困境来优化时间。可能值得考虑不同的数据类型;例如,虽然NSArray似乎是简单扁平容器最合理的选择,但如果您实际上不需要订购信息,最好使用NSSet;这有一个额外的好处,它不会存储相同的对象(使用-isEqual:
计算)两次。如果你想跟踪重复项,但不需要排序,可以使用NSCountedSet,它表现为NSSet,除了它跟踪每个对象被添加/删除的次数,而不实际存储重复项。
答案 2 :(得分:1)
就我所见,您必须实施自己的类别。