7

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。我错过了什么吗?有人知道另一种标准方法吗?否则我必须把它写成一个类别方法。

4

3 回答 3

13

较新的 NSArray 版本(OSX 10.6 和 iOS 4)提供了该indexesOfObjectsPassingTest:方法。

NSIndexSet *indexesOfObjects = [[array1 indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
    return [array2 containsObject:obj];
}];
于 2013-02-06T16:00:05.453 回答
6

使用集合来指定要查找的对象可能很有用,例如:

- (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,除了它跟踪每个对象添加/删除的次数而不实际存储重复项。

于 2009-05-31T14:37:33.033 回答
1

据我所知,您必须实现自己的类别。

于 2009-05-25T08:15:32.217 回答