我不得不NSArrays:试图优化一些循环代码
- _kundenArray - 持有所有客户(目前约有3000)
- _bestellungenMutArr - 持有所有订单(目前约8000)
〜 ~~~~
EDIT2 - 补充说:
我的两个阵列得到通过解析单独的csv文件填充,所以最初我不知道客户和订单之间的任何关系。
~~~~~
为每一位客户我试图确定它的订单,更特别是其最后的顺序(日期)。
我估计有一半以上的顾客没有任何订单,有的有几个,有的很多。
一开始我有2个嵌套循环,外部遍历所有客户,内部遍历所有订单。其结果超过(3000 * 8000)比较(赋予附加的代码)。
经过一番思考之后,我意识到我只有有效的订单,即每个订单都有一个客户ID,并且对于每个客户ID,我都有一个具有相同ID的现有客户。 为了减少内部循环的开销,我根据客户ID订购了两个数组。
这意味着第一个订单对应于我的第一批客户。例如:
- _kundenArray [0]具有客户ID为
- _bestellungenMutArr [0-3]已以便与IDS 24-27,通过每个客户订购
然后将每个相应的订单收集到一个数组中,直到达到一个订单,其客户ID与我的客户ID不符。然后退出(中断)我的循环,从包含所有订单(_bestellungenMutArr)的数组中删除我收集的订单,然后继续处理下一个客户。
从阵列中移除对象的速度非常快,因为对象是ALL位于大数组的开头。 (见图表说明不同的数组操作here的性能在ridiculousfish
检查仪器的时间简档数据,我发现的时候,超过99%都花在去除对象的仪器输出: 然后我想出了利用enumerateObjectsUsingBlock的索引的想法,而不是使用内部循环的快速枚举,我使用了块枚举器。为了在内部循环中实现相同的开销减少(即从不处理订单两次我跟踪后续用于下一次迭代(对于下一个客户)的偏移量的索引。这样我规避了从数组中删除对象,我认为这可能是一个非常漂亮的想法。
检查时间简档输出原来它不是:
因此,使用该变体通过使用removeObjectsInArray方法(约1500倍)从阵列的对象是快8倍左右,不是简单地保持追踪索引?
这是预计还是我错过了什么?
阵列移除/快速列举的变体:
- (void) determineLastOrders
{
for (Kunde * kunde in _kundenArray)
{
NSMutableArray *bestellungenToRemove = [[NSMutableArray alloc] init];
/* go through all (remaining) orders (after the loop the matching will be removed) and determine the next ones to remove */
for (Bestellung * bestellung in _bestellungenMutArr)
{
if ([[bestellung bestKdNr] isEqualToString:kunde.kdnr])
{
if (kunde.lastOrder == nil)
{
kunde.lastOrder = _orangeDate; //"init"
}
else if ([kunde.lastOrder compare:[bestellung bestDatum]] == NSOrderedAscending)
{
kunde.lastOrder = [bestellung bestDatum];
}
//As this Bestellung already has had a date comparison (equal by kdnr)
//we won't need to visit it again by our next customer
[bestellungenToRemove addObject:bestellung];
}
else
{ //as all orders are ordered by the customer id we can abort iteration
//after we went past the current id
break;
}
}
[_bestellungenMutArr removeObjectsInArray: bestellungenToRemove];
}
}
和检查索引/块枚举变体:
- (void) determineLastOrders
{
__block NSUInteger bestIndex = 0;
for (Kunde * __block kunde in _kundenArray)
{
/* go through all (remaining) orders (after the loop the matching will be removed) and determine the next ones to remove */
[_bestellungenMutArr enumerateObjectsUsingBlock: ^(Bestellung * bestellung, NSUInteger idx, BOOL *stop)
{
if (idx >= (bestIndex))
{
if ([[bestellung bestKdNr] isEqualToString:kunde.kdnr])
{
if (kunde.lastOrder == nil)
{
kunde.lastOrder = _orangeDate; //"init"
}
else if ([kunde.lastOrder compare:[bestellung bestDatum]] == NSOrderedAscending)
{
kunde.lastOrder = [bestellung bestDatum];
}
}
else
{ //as all orders are ordered by the customer id we can abort iteration
//after we went past the current id
bestIndex = idx+1;
*stop = YES;
}
}
}];
}
}
提前感谢!
编辑:另一个问题刚刚出现在我的脑海里。目前 - 在我的第一个代码片段中,我总是在每个内部循环之后调用removeObjectsInArray方法。如果客户没有订单,我删除一个空数组(即试图删除零?)。 我的猜测是,如果传递一个空数组,那么该方法退出的指令就是移除指令,因此比每个循环检查内容的小数组效率更高。或者我错了?
为什么不使用NSDictionary来存储特定客户的订单? NSDictionary的键值对可以是“kunde.kdnr-NSArray-Of-Orders”。这将允许一次获得客户的所有订单,而不是迭代完整的数组订单集。 – gagarwal
如果这些数据在核心数据中,查询您要查找的内容会更容易。 –
@gagarwall我解析两个单独的csv文件。一个包含所有客户,另一个包含所有订单。一开始我不知道哪个订单对应哪个客户。因此,无论哪种方式,我都必须通过两者来确定关系。 –