2012-04-12 14 views
5


Estoy tratando de encontrar una buena solución para dividir un conjunto de diccionarios en diccionarios más pequeños con un valor común entre ellos.
Aquí es un ejemplo i JSON, comienzo de esta:Dividir un NSArray en matrices codificadas con valores clave más pequeños utilizando un par clave-valor común entre los objetos

{ 
    "field": [ 
    { 
     "id": 6, 
     "name": "Andrea" 
    }, 
    { 
     "id": 67, 
     "name": "Francesco" 
    }, 
    { 
     "id": 8, 
     "name": "Maria" 
    }, 
    { 
     "id": 6, 
     "name": "Paolo" 
    }, 
    { 
     "id": 67, 
     "name": "Sara" 
    } 
    ] 
} 

Me gustaría conseguir un resultado como:

{ 
    "field": [ 
    { 
     "6": [ 
     { 
      "name": "Andrea", 
      "id": 6 
     }, 
     { 
      "name": "Paolo", 
      "id": 6 
     } 
     ], 
     "67": [ 
     { 
      "name": "Sara", 
      "id": 67 
     }, 
     { 
      "name": "Francesco", 
      "id": 67 
     } 
     ], 
     "8": [ 
     { 
      "name": "Maria", 
      "id": 8 
     } 
     ] 
    } 
    ] 
} 

he conseguido con este código, funciona, pero yo estoy preguntando si existe algo más correcto y rápido:

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; 

} 

Respuesta

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]; 
} 

Si hay muchos ID, puede acelerar esto un poco construyendo un predicado con una referencia variable fuera del ciclo y luego simplemente sustituyendo la variable para producir el predicado específico del id para cada paso a través del ciclo .

Por cierto, en su pregunta, el resultado "campo" sigue siendo una matriz por alguna razón. No creo que deba ser así.


Actualizado a hacer un solo pase:

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]; 
} 
+0

Gracias Ken, voy a banco de los dos y publicar el resultado, THX – Andrea

+0

he hecho un pequeño banco en la tarjeta SIM: el método original toma 0.000098 el que sugeriste 0.002735. Supongo que la principal diferencia es que con la mía solo haces un ciclo una vez, usando el predicado que ciclos una cantidad de veces igual al número de los identificadores. – Andrea

+0

Es cierto. He actualizado mi respuesta con un enfoque que solo hace una pasada. –

Cuestiones relacionadas