我有一个名为Topic的类的已排序可变数组。主题代表一系列出版物。我在表中提供主题,并定期从Web服务中获取新的出版物。当新出版物到来时,我想用动画添加到表格中。
困扰我的是我需要做的计算工作才能添加到此数组中,并回答正确的索引路径。有人可以提出比这更直接的方式:
// 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!
我想,第一次搜索无法解决。但是有没有更有效的方法来为数组添加新东西,维护排序并记住它放在哪里?
答案 0 :(得分:3)
将值插入排序列表非常简单。想想如何将数字“3”插入到“1,2,7,9”列表中。你想做同样的事情。
使用for
循环按索引遍历数组。
对于每个对象,使用compareToTopic:
将其与要插入的对象进行比较。
当您找到要插入的相应索引时,请使用-[NSArray insertObject:atIndex:]
插入它。
然后返回带有该索引的NSIndexPath
。
编辑:并且,正如其他答案所指出的那样,二元搜索会更快 - 但要想做对,肯定更难。
答案 1 :(得分:2)
这几乎肯定不是问题; NSArrays
are 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;
}
请注意,我没有对此进行测试,抱歉。
我不确定这实际上比你写它的方式更好或更快。
不要担心计算机正在做的工作,除非它明显地做得太慢。
答案 2 :(得分:1)
我猜你所做的是正确的。还有另一种方式。您可以编写自己的二进制搜索实现方法。 (其中只有几行代码)。并且您可以检索新对象应该适合的索引。并使用insertObject:atIndex:方法将新对象添加到所需的索引。