NSMutableArray自定义对象 - >类似词典和NSDictionaries的NSMutableArray的NSMutableArray

时间:2016-04-14 00:32:41

标签: objective-c algorithm nsmutablearray nsarray nsdictionary

我在创建一个自定义对象数组的NSMutableArray到一个字典数组和单个字典数组(不在数组中)时遇到了问题。

我目前有一个Person对象的NSMutableArray。我遍历这些Person对象来创建每个对象的NSDictionaries。这些词典有三个键:

NSString *firstName;
NSString *lastName;
Person *id;

这些词典中的一些将具有完全相同的名字和姓氏,但是人物ID 总是不同。我想将此对象的NSMutableArray转换为NSMutableArrays和NSDictionaries的NSMutableArray - NSMutableArrays将是具有相同firstName和lastName的NSDictionaries,而单独的NSDictionaries将是没有firstName和lastName的对象与原始NSMutableArray中的任何其他Person共同。

我希望最终结果的视觉效果如下:

                  |                    |--   NSDictionary (john, smith, id)
                  |                    |--   NSDictionary (john, smith, id)
                  |--  NSMutableArray  |--   NSDictionary (john, smith, id)
                  |                    |--   NSDictionary (john, smith, id)
                  |                    |--   NSDictionary (john, smith, id)
                  |
                  |                    |--   NSDictionary (bill, jones, id)
     people       |--  NSMutableArray  |--   NSDictionary (bill, jones, id)
(NSMutableArray)  |                    |--   NSDictionary (bill, jones, id)
                  |
                  |--  NSDictionary (mike, smith, id)
                  |
                  |--  NSDictionary (mike, jones, id)
                  |
                  |--  NSDictionary (john, jones, id)

我目前的实施情况如下:

- (NSMutableArray*)organizeForSearchResults:(NSMutableArray*)c {

  NSMutableArray *returnArray = [NSMutableArray alloc] init];

  // iterate through every person in the incoming crate
  @autoreleasepool {
    for (Person *person in c) {

      // create a new person dictionary
      NSDictionary *personDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:
                                        person, @"person",
                                        person.firstName, @"firstName",
                                        record.lastName, @"lastName",
                                        nil];

      // if there are already objects in the top level c array
      if (returnArray.count > 0) {
        for (id object in returnArray) {

          // the object in returnArray is an array of record dictionaries
          if ([object isKindOfClass:[NSMutableArray class]]) {

            // if the first dictionary object in the array has the same firstName
            // and lastName, add the new person dict to the existing array of dicts
            NSString *firstName = [(NSDictionary*)object[0] objectForKey:@"firstName"];
            NSString *lastName = [(NSDictionary*)object[0] objectForKey:@"lastName"];
            if ([firstName isEqualToString:person.firstName] && [lastName isEqualToString:person.lastName]) {
              [object addObject:personDictionary];
            }
          }
          // if the object is a person dictionary, see if it matches the current dictionary
          else if ([object isKindOfClass:[NSDictionary class]]) {
            NSString *firstName = [(NSDictionary*)object objectForKey:@"firstName"];
            NSString *lastName = [(NSDictionary*)object objectForKey:@"lastName"];

            // if the current object matches the new person dict, we need to
            // create a new array with both the existing person dict and the
            // new person dict, add that array to returnArray, and remove the
            // old person dict
            if ([firstName isEqualToString:record.firstName] && [lastName isEqualToString:record.lastName]) {
              NSMutableArray *newArray = [[NSMutableArray alloc] initWithCapacity:2];
              [newArray addObject:object];
              [newArray addObject:personDictionary];
              [returnArray addObject:newArray];
              [returnArray removeObject:object];
            }
            // the new person dict does not match an existing array, so add it as
            // a single item in personArray
            else {
              [personArray addObject:personDictionary];
            }
          }
        }
      }
      // there are no objects in personArray, so just add this person dict
      else {
        [personArray addObject:personDictionary];
      }
    }
  }

  return personArray;
}

到目前为止,我的实现在功能上是正确的,我相信,但我显然会收到*** Collection <__NSArrayM:> was mutated while being enumerated.错误,因为我在枚举时修改了NSMutableArray。我觉得我完全迷失了如何正确实现这一点 - 有没有人有另外一个如何实现这个目标的策略?

1 个答案:

答案 0 :(得分:0)

  

我相信,到目前为止我的实现在功能上是正确的,

抱歉,但我认为你会发现它不是。然而,这是简单的调试,我相信你会把它整理出来。

  

但我显然得到了*** Collection&lt; __ NSArrayM:&gt;在被列举时被突变。错误

观察1:您可以通过改变枚举的数组来解决问题 - 即使用for(a in b)样式迭代进行处理。如果您改为使用for(a; b; c)来遍历数组的索引,那么可以随时改变数组,您也可以使用- replaceObjectAtIndex:withObject:方法而不是{ {1}} / addObject:对。

对迭代样式进行这样的更改不需要来修复您的问题,但这样做可能有意义。

观察2:您当前的迭代遍历整个数组,但是对于每次迭代执行,最多只进行一次更改 - 您将项添加到数组,或者替换字典元素带有数组元素。一旦你做了改变,就可以终止循环 - 其余的迭代不会做任何有用的事情。

但是,如果您使用removeObject:样式,那些冗余迭代将执行一些不会有用的操作 - 它们会导致您在更改数组后尝试继续迭代时看到的错误。 / p>

for in语句可用于终止迭代。如果在进行变异控制后使用其中一个,则在迭代后转移到语句。该语句适用于任何一种迭代方式。

这应该足以让你解决这个问题,但是你应该检查一下你的逻辑 - 它可能还没有达到预期的效果。

BTW您可能希望更改为现代Objective-C语法以进行字典构建和键索引,它会缩短您的代码并使其更具可读性。

HTH