使用对象之间的公共键值对在较小的键值编码数组中拆分NSArray

And*_*rea 5 arrays sorting split objective-c


我试图找到一个很好的解决方案,将一个字典数组拆分成一个较小的字典,并以它们之间的公共值为键.
这是一个我JSON的例子,我从这开始:

{
  "field": [
    {
      "id": 6,
      "name": "Andrea"
    },
    {
      "id": 67,
      "name": "Francesco"
    },
    {
      "id": 8,
      "name": "Maria"
    },
    {
      "id": 6,
      "name": "Paolo"
    },
    {
      "id": 67,
      "name": "Sara"
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

我想得到一个结果:

{
  "field": [
    {
      "6": [
        {
          "name": "Andrea",
          "id": 6
        },
        {
          "name": "Paolo",
          "id": 6
        }
      ],
      "67": [
        {
          "name": "Sara",
          "id": 67
        },
        {
          "name": "Francesco",
          "id": 67
        }
      ],
      "8": [
        {
          "name": "Maria",
          "id": 8
        }
      ]
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

我管理使用这个代码,它的工作原理,但我想知道是否存在更正确和更快的东西:

    NSArray * array = ...;
    NSSortDescriptor *sorter1=[[NSSortDescriptor alloc]initWithKey:@"id" ascending:YES selector:@selector(compare:)];
    NSSortDescriptor *sorter2=[[NSSortDescriptor alloc]initWithKey:@"name" ascending:YES selector:@selector(caseInsensitiveCompare:)];
    NSArray *sortDescriptors=[NSArray arrayWithObjects:sorter1,sorter2,nil];
    array = [array sortedArrayUsingDescriptors:sortDescriptors];    
    //////////////////////////////SPLITTER
    NSMutableArray * subcategorySplittedArray = [[NSMutableArray alloc]initWithCapacity:30];
    NSNumber * lastID=[[array objectAtIndex:0]objectForKey:@"id"];
    NSMutableArray * shopArray = [[NSMutableArray alloc]initWithCapacity:100];
    NSMutableDictionary * catDict = nil;
    for (NSDictionary * dict in array) {
        NSNumber * catID = [dict objectForKey:@"id"];
        if ([lastID isEqualToNumber:catID]) {
            [shopArray addObject:dict];
        }
        else {

            catDict = [[NSMutableDictionary alloc]init ];
            [catDict setObject:[shopArray copy] forKey:lastID];
            [subcategorySplittedArray addObject:catDict];
            [shopArray removeAllObjects];
            [shopArray addObject:dict];
            lastID = catID;
        }
    }
    catDict = [[NSMutableDictionary alloc]init ];
    [catDict setObject:[shopArray copy] forKey:lastID];
    [subcategorySplittedArray addObject:catDict];
    ////////////////////////////////////
    return subcategorySplittedArray;

}
Run Code Online (Sandbox Code Playgroud)

Ken*_*ses 9

NSMutableDictionary* result = [NSMutableDictionary dictionary];
NSArray* ids = [array valueWithKey:@"id"];
NSSet* uniqueIDs = [NSSet setWithArray:ids];
for (NSNumber* anID in uniqueIDs)
{
    NSPredicate* pred = [NSPredicate predicateWithFormat:@"id == %@", anID];
    NSArray* dictsForID = [array filteredArrayUsingPredicate:pred];
    [result setObject:dictsForID forKey:anID];
}
Run Code Online (Sandbox Code Playgroud)

如果有很多ID,你可以通过在循环之外构建一个带有变量引用的谓词来加速这一点,然后只需用变量代入就可以为循环中的每次传递产生特定于id的谓词.

顺便说一下,在你的问题中,由于某种原因,结果"字段"仍然是一个数组.我不认为它需要.


更新只进行一次传递:

NSMutableDictionary* result = [NSMutableDictionary dictionary];
for (NSDictionary* dict in array)
{
    NSNumber* anID = [dict objectForKey:@"id"];
    NSMutableArray* resultsForID = [result objectForKey:anID];
    if (!resultsForID)
    {
        resultsForID = [NSMutableArray array];
        [result setObject:resultsForID forKey:anID];
    }

    [resultsForID addObject:dict];
}
Run Code Online (Sandbox Code Playgroud)