2012-03-26 47 views
0

我有一個名爲Topic的類的已排序可變數組。主題代表一系列出版物。我將這些主題呈現在表格中,並定期從Web服務中獲取新的出版物。當新的出版物到達時,我想用動畫添加到表格中。添加對象到已排序的NSMutable數組並回答索引路徑

讓我煩惱的是我需要做的計算工作來添加到這個數組中,並回答正確的索引路徑。有人可以建議一個比這更直接的方式:

// add a publication to the topic model. if the publication has a new topic, answer 
// the index path of the new topic 
- (NSIndexPath *)addPublication:(Publication *)pub { 

    // first a search to fit into an existing topic 
    NSNumber *topicId = [pub valueForKey:@"topic_id"]; 
    for (Topic *topic in self.topics) { 
     if ([topicId isEqualToNumber:[topic valueForKey:"id"]]) { 
      // this publication is part of an existing topic, no new index path 
      [topic addPublication:pub]; 
      return nil; 
     } 
    } 

    // the publication must have a new topic, add a new topic (and therefore a new row) 
    Topic *topic = [[Topic alloc] initWithPublication:publication]; 
    [self.topics addObject:topic]; 

    // sort it into position 
    [self.topics sortUsingSelector:@selector(compareToTopic:)]; 

    // oh no, we want to return an index path, but where did it sort to? 
    // yikes, another search! 
    NSInteger row = [self.topics indexOfObject:topic]; 
    return [NSIndexPath indexPathForRow:row inSection:0]; 
} 

// call this in a loop for all the publications I fetch from the server, 
// collect the index paths for table animations 
// so much computation, poor user's phone is going to melt! 

有沒有得到周圍的第一次搜索,我猜。但是有沒有更有效的方法來將新事物添加到數組中,保持排序並記住它放置的位置?

回答

2

這幾乎肯定不是問題; NSArraysare actually hashes,搜索速度比真實數組快很多。反正你可能有多少個話題?

儘管如此,如果您衡量性能並發現它很差,您可以使用B-tree進行研究; Kurt Revis在下面評論了Core Foundation的一個類似結構(binary heap)的鏈接:CFBinaryHeap

另一個選項(也需要測量)可能是在您第一次走陣時進行比較;你可以標記當場直接做插入:

NSUInteger insertIndex = 0; 
NSComparisonResult prevOrder = NSOrderedDescending; 
for (Topic *topic in self.topics) { 
    NSComparisonResult order = [topicId compareToTopic:topic]; 
    if (NSOrderedSame == order) { 
     // this publication is part of an existing topic, no new index path 
     [topic addPublication:pub]; 
     return nil; 
    } 
    else if(prevOrder == NSOrderedDescending && 
      order == NSOrderedAscending) 
    { 
     break; 
    } 
    insertIndex++; 
    prevOrder = order; 
} 

請注意,我沒有測試過這一點,不好意思。但是,我不確定這實際上是比你寫的方式更好還是更快的方式。

不要擔心計算機正在做的工作,除非它是明顯是這樣做太慢了。

+0

他擔心的是他需要在添加新對象時總是對數組進行排序。 – 2012-03-26 05:33:28

+2

@ charith:我的觀點是,現有代碼的性能不太可能成爲問題。我相信這是一個擔心計算機在做多少工作而沒有真正看到需要多少時間的情況。 – 2012-03-26 05:37:44

+0

[CFBinaryHeap](http://developer.apple.com/library/mac/#documentation/CoreFoundation/Reference/CFBinaryHeapRef/Reference/reference.html)可能是滾動自己的B樹的好選擇。 – 2012-03-26 05:38:22

3

將值插入排序列表非常簡單。例如,考慮如何將數字「3」插入列表「1,2,7,9」中。你想要做同樣的事情。

使用for循環通過索引循環訪問數組。

對於每個對象,請使用compareToTopic:將其與要插入的對象進行比較。

當您找到要插入的適當索引時,使用-[NSArray insertObject:atIndex:]來插入它。

然後用該索引返回一個NSIndexPath

編輯:而且,正如其他答案指出的那樣,二分法搜索會更快 - 但確實會更棘手。

1

你所做的是正確的我猜。還有另一種方法。您可以編寫自己的二進制搜索實現方法。 (只有幾行代碼)。您可以檢索新對象應該放入的索引。然後使用insertObject:atIndex:method將新對象添加到所需的索引。

相關問題