2014-07-03 82 views
1

我不得不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的索引的想法,而不是使用内部循环的快速枚举,我使用了块枚举器。为了在内部循环中实现相同的开销减少(即从不处理订单两次我跟踪后续用于下一次迭代(对于下一个客户)的偏移量的索引。这样我规避了从数组中删除对象,我认为这可能是一个非常漂亮的想法。

检查时间简档输出原来它不是: enter image description here

因此,使用该变体通过使用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方法。如果客户没有订单,我删除一个空数组(即试图删除零?)。 我的猜测是,如果传递一个空数组,那么该方法退出的指令就是移除指令,因此比每个循环检查内容的小数组效率更高。或者我错了?

+0

为什么不使用NSDictionary来存储特定客户的订单? NSDictionary的键值对可以是“kunde.kdnr-NSArray-Of-Orders”。这将允许一次获得客户的所有订单,而不是迭代完整的数组订单集。 – gagarwal

+1

如果这些数据在核心数据中,查询您要查找的内容会更容易。 –

+0

@gagarwall我解析两个单独的csv文件。一个包含所有客户,另一个包含所有订单。一开始我不知道哪个订单对应哪个客户。因此,无论哪种方式,我都必须通过两者来确定关系。 –

回答

1

第二个例子比较好,但由于enumerateObjectsUsingBlock:...每次都从头开始,所以您仍然通过更多的订单来列举每个客户的订单。 (与您的第一个代码示例不同,您可以尝试使用enumerateObjectsAtIndexes:...来代替传入以从bestIndex开始的NSRange制作的索引集。

或者,你可以使用正常的循环:for (NSUInteger i = bestIndex; i < [_bestellungenMutArr count]; i++)这可能会更快。 optization的

+0

这真是太神奇了!使用正常循环时,该方法的时间消耗下降了11毫秒,比迄今为止我的最佳解决方案快50倍以上。 非常感谢你! –

0

多了一个层次:

int count = [_bestellungenMutArr count]; 
for (NSUInteger i = bestIndex; i < count; i++) 

为什么呢?

现在每次都不会循环[_bestellungenMutArr计数]。