【问题标题】:best way to populate NSArray in this algorithm在此算法中填充 NSArray 的最佳方法
【发布时间】:2012-10-23 02:11:53
【问题描述】:

我打算制作一个执行以下操作的程序:

Create an NSArray populated with numbers from 1 to 100,000.
Loop over some code that deletes certain elements of the NSArray when certain conditions are met.
Store the resultant NSArray.

但是,上述步骤也会循环多次,因此我需要一种快速的方法来制作这个具有 100,000 个数字元素的 NSArray。

那么最快的方法是什么?

是否有替代使用 for 循环迭代填充数组的方法?比如 NSArray 方法可以为我快速完成这项工作吗?

或者也许我可以在第一次以任何方式制作具有 100,000 个数字的 NSArray。然后使用方法 arraywithArray 创建每个新的 NSArray(用于步骤 1)? (这样做更快吗?)

或者也许你有完全不同的想法来实现我想要的。

编辑:在上面的帖子中用 NSMutableArray 替换 NSArray

【问题讨论】:

  • 为什么需要这个 100000 个元素的数组?

标签: objective-c ios arrays nsarray


【解决方案1】:

很难提前判断哪种方法最快。我喜欢基于块的功能,例如

NSMutableArray *array = ...; // your mutable array

NSIndexSet *toBeRemoved = [array indexesOfObjectsPassingTest:^BOOL(NSNumber *num, NSUInteger idx, BOOL *stop) {
    // Block is called for each number "num" in the array.
    // return YES if the element should be removed and NO otherwise;
}];
[array removeObjectsAtIndexes:toBeRemoved];

您可能应该从正确工作的算法开始,然后使用 Instruments 进行分析。

【讨论】:

    【解决方案2】:

    您可能想查看NSMutableIndexSet。它旨在有效地存储数字范围。

    你可以这样初始化它:

    NSMutableIndexSet *set = [[NSMutableIndexSet alloc]
        initWithIndexesInRange:NSMakeRange(1, 100000)];
    

    然后您可以像这样从中删除例如 123:

    [set removeIndex:123];
    

    或者您可以像这样删除 400 到 409:

    [set removeIndexesInRange:NSMakeRange(400, 10)];
    

    您可以像这样遍历集合中的所有剩余索引:

    [set enumerateIndexesUsingBlock:^(NSUInteger i, BOOL *stop) {
        NSLog(@"set still includes %lu", (unsigned long)i);
    }];
    

    或者,更有效的是,像这样:

    [set enumerateRangesUsingBlock:^(NSRange range, BOOL *stop) {
        NSLog(@"set still includes %lu indexes starting at %lu",
            (unsigned long)range.length, (unsigned long)range.location);
    }];
    

    【讨论】:

      【解决方案3】:

      我很确定使用 c 数组创建数组会是最快的,然后从中创建一个NSArray(即将推出基准测试)。根据您要删除数字的方式,在初始循环中执行此操作可能是最快的:

      const int max_num = 100000;
      ...
      id *nums = malloc(max_num * sizeof(*nums));
      int c = 0;
      for(int i = 1; i <= max_num; i++) {
          if(!should_skip(i)) nums[c++] = @(i);
      }
      NSArray *nsa = [NSArray arrayWithObjects:nums count:c];
      

      第一个基准测试有点令人惊讶。对于 100M 个对象:

      NSArray alloc init:             8.6s
      NSArray alloc initWithCapacity: 8.6s
      id *nums:                       6.4s
      

      所以数组更快,但没有我预期的那么快。

      【讨论】:

      • +1,不仅更快,而且更轻。 NSArray 会因为保持其内容被索引而受到惩罚。
      【解决方案4】:

      您可以使用快速枚举来搜索数组。

      for(NSNumber item in myArrayOfNumbers)
      {
         If(some condition)
         {
              NSLog(@"Found an Item: %@",item);
          }
      }
      

      【讨论】:

      • 请考虑到我在火车上用手机,所以布局不太好。
      • 需要注意的是,使用快速枚举时不能修改数组。
      【解决方案5】:

      您可能需要重新考虑您在这里所做的事情。问问自己为什么想要这样一个数组。如果您的目标是处理任意大的整数集合,您可能更喜欢使用NSIndexSet(及其可变对应物)。

      如果您真的想以最有效的方式操作NSArray,您将需要实现一个专门针对此类工作进行优化的子类。

      【讨论】:

        猜你喜欢
        • 2017-01-01
        • 1970-01-01
        • 2020-01-08
        • 2015-12-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-23
        • 2010-10-05
        相关资源
        最近更新 更多