Domanda

NSArray ha metodi utili per trovare oggetti per gli indici specificati

// To find objects by indexes
- (id)objectAtIndex:(NSUInteger)index
- (NSArray *)objectsAtIndexes:(NSIndexSet *)indexes

// To find index by object
- (NSUInteger)indexOfObject:(id)anObject

Tuttavia, voglio ottenere NSIndexSet (più indici) per determinati oggetti. Qualcosa di simile:

- (NSIndexSet *)indexesOfObjects:(NSArray *)objects

Questo metodo non esiste per NSArray. Mi sto perdendo qualcosa? Qualcuno sa un altro metodo standard? Altrimenti devo scrivere questo come un metodo di categoria.

È stato utile?

Soluzione

Potrebbe essere utile per la sua attuazione mediante una serie di specificare gli oggetti da trovare, come ad esempio:

- (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] );
}

Ciò richiede la visita ogni oggetto nella matrice, ma almeno fa solo una volta e si avvale di enumerazione veloce, mentre farlo. Utilizzando un NSSet e prova di ciascun oggetto nell'array contro tale set è anche molto più veloce di test per l'inclusione in una matrice.

C'è un potenziale di ottimizzazione qui, ma sarebbe svolta nel caso in cui un singolo oggetto viene memorizzato nella matrice di ricezione più volte:

if ( [set containsObject: obj] )
{
    [indices addIndex: index];
    if ( [indices count] == [set count] )
        break;
}

In questo modo se si esegue la scansione di un array di 20'000-oggetto per due oggetti e sono entrambi dentro i primi dieci, sarete in grado di evitare la scansione degli altri 19'990 oggetti nella matrice. Come ho detto, però, che non aiuta se l'array contiene duplicati, perché si fermerà non appena viene trovata 2 indici (anche se entrambi punto allo stesso oggetto).

Detto questo , sono d'accordo con il commento di Mike sopra. Le probabilità sono che stai impostando per un po 'di dolore provenire ottimizzazione in tempo. Può valere la pena di pensare a diversi tipi di dati; per esempio, mentre NSArray sembra la scelta più logica per un semplice contenitore piatta, se non effettivamente bisogno le informazioni ordinazione è meglio utilizzare un NSSet invece; Questo ha il vantaggio che non memorizza lo stesso oggetto (calcolato usando -isEqual:) due volte. Se si vuole tenere traccia di duplicati, ma non hanno bisogno di ordine, è possibile utilizzare NSCountedSet, che si comporta come NSSet tranne che tiene traccia di quante volte è stato aggiunto / rimosso ogni oggetto senza realmente memorizzare i duplicati.

Altri suggerimenti

versioni più recenti NSArray (OSX 10.6 e iOS 4) fornisce il metodo indexesOfObjectsPassingTest:.

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

È necessario implementare il proprio categoria, per quanto posso vedere.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top