Вопрос

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.Я что-то пропустил?Кто-нибудь знает другой стандартный метод?В противном случае мне придется записать это как метод категории.

Это было полезно?

Решение

Возможно, было бы полезно реализовать его, используя набор для указания объектов для поиска, например:

- (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, за исключением того, что он отслеживает, сколько раз каждый объект был добавлен/удален, без фактического сохранения дубликатов.

Другие советы

Более новые версии NSArray (OSX 10.6 и iOS 4) предоставляют indexesOfObjectsPassingTest: метод.

NSIndexSet *indexesOfObjects = [[array1 indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
    return [array2 containsObject:obj];
}];

Насколько я понимаю, вам нужно реализовать свою собственную категорию.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top