2009-05-25 50 views
7

NSArray中有一些有用的方法來尋找對象指定索引從NSArray中獲取的NSIndexSet

// 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不存在。我錯過了什麼嗎?有人知道另一種標準方法嗎?否則,我必須把它寫成一個類別方法。

回答

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個索引(即使它們都指向同一個對象),它也會停止。

話雖如此,,我同意上面的Mike的評論。有機會,你正在設置自己的一些痛苦來優化時間。可能值得思考不同的數據類型;例如,雖然NSArray似乎是一個簡單的扁平容器的最合理的選擇,但如果您實際上不需要訂購信息,則最好使用NSSet;這具有額外的優點,即它不會存儲兩次相同的對象(使用-isEqual:計算)。如果你想跟蹤重複,但不需要排序,你可以使用NSCountedSet,它的行爲像NSSet,除了它跟蹤每個對象被添加/刪除多少次而沒有實際存儲重複。

+2

+1請注意:索引和索引在英文中都是正確的,但Cocoa始終使用「索引」,所以最好遵守該術語,至少對於方法名稱。 – 2009-07-07 15:22:38

1

就我所見,您必須實現您自己的類別。

+2

請注意,雖然希望這種方法是一個設計缺陷的強烈信號。 -indexOfObject:通過搜索數組中的每個對象來工作,因此對於大數組或多個搜索變得非常緩慢。重新思考你的數據結構以獲得更明智的東西。 – 2009-05-25 21:51:13

13

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

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