¿Reconstruir un NSArray agrupando objetos que tienen números de id coincidentes?

Tengo un NSArray y cada objeto en la matriz tiene un ID de grupo y un nombre. Cada objeto es único, pero hay muchos con el mismo ID de grupo. ¿Hay alguna manera de separar el arreglo y reconstruirlo para que los nombres se agrupen en un solo objeto con el groubId correspondiente? Aquí se muestra cómo se ve la matriz en este momento:

2013-03-12 20:50:05.572 appName[4102:702] the array: ( { groupId = 1; name = "Dan"; }, { groupId = 1; name = "Matt"; }, { groupId = 2; name = "Steve"; }, { groupId = 2; name = "Mike"; }, { groupId = 3; name = "John"; }, { groupId = 4; name = "Kevin"; } ) 

Esto es lo que me gustaría que se vea así:

 2013-03-12 20:50:05.572 appName[4102:702] the array: ( { groupId = 1; name1 = "Dan"; name2 = "Matt"; }, { groupId = 2; name1 = "Steve"; name2 = "Mike"; }, { groupId = 3; name = "John"; }, { groupId = 4; name = "Kevin"; } ) 

EDITAR: He intentado y fallé con muchos bashs, casi en la línea de algo como esto (recreación descuidada, pero para dar una idea):

 int idNum = 0; for (NSDictionary *arrObj in tempArr){ NSString *check1 = [NSString stringWithFormat:@"%@",[arrObj valueForKey:@"groupId"]]; NSString *check2 = [NSString stringWithFormat:@"%@",[[newDict valueForKey:@"groupId"]]; if (check1 == check2){ NSString *nameStr = [NSString stringWithFormat:@"name_%d",idNum]; [newDict setValue:[arrObj valueForKey:@"name"] forKey:nameStr]; } else { [newDict setValue:arrObj forKey:@"object"]; } idNum++; } 

 NSArray *array = @[@{@"groupId" : @"1", @"name" : @"matt"}, @{@"groupId" : @"2", @"name" : @"john"}, @{@"groupId" : @"3", @"name" : @"steve"}, @{@"groupId" : @"4", @"name" : @"alice"}, @{@"groupId" : @"1", @"name" : @"bill"}, @{@"groupId" : @"2", @"name" : @"bob"}, @{@"groupId" : @"3", @"name" : @"jack"}, @{@"groupId" : @"4", @"name" : @"dan"}, @{@"groupId" : @"1", @"name" : @"kevin"}, @{@"groupId" : @"2", @"name" : @"mike"}, @{@"groupId" : @"3", @"name" : @"daniel"}, ]; NSMutableArray *resultArray = [NSMutableArray new]; NSArray *groups = [array valueForKeyPath:@"@distinctUnionOfObjects.groupId"]; for (NSString *groupId in groups) { NSMutableDictionary *entry = [NSMutableDictionary new]; [entry setObject:groupId forKey:@"groupId"]; NSArray *groupNames = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"groupId = %@", groupId]]; for (int i = 0; i < groupNames.count; i++) { NSString *name = [[groupNames objectAtIndex:i] objectForKey:@"name"]; [entry setObject:name forKey:[NSString stringWithFormat:@"name%d", i + 1]]; } [resultArray addObject:entry]; } NSLog(@"%@", resultArray); 

Salida:

  ( { groupId = 3; name1 = steve; name2 = jack; name3 = daniel; }, { groupId = 4; name1 = alice; name2 = dan; }, { groupId = 1; name1 = matt; name2 = bill; name3 = kevin; }, { groupId = 2; name1 = john; name2 = bob; name3 = mike; } ) 

Esto requiere un NSDictionary de NSArrays. No hay una manera rápida y elegante: tendrías que desplazarte por la fuente.

 NSMutableDictionary *d = [NSMutableDictionary dictionaryWithCapacity:10]; //Or use alloc/init for(SomeObject o in appname) //What's the type of objects? you tell me { NSObject *ID = [o objectForKey: @"groupId"]; NSMutableArray *a = [d objectForKey: ID]; if(a == nil) { a = [NSMutableArray arrayWithCapacity: 10]; [d setObject:a forKey: ID]; } [a addObject: [o objectForKey: @"name"]]; } 

EDITAR: editado para no asumir el tipo de datos de la clave.

Esto es similar a la respuesta de Seva, pero se puede agregar como un método de categoría en NSArray:

 /// @return A dictionary of NSMutableArrays - (NSDictionary *)abc_groupIntoDictionary:(id(^)(id object))keyFromObjectCallback { NSParameterAssert(keyFromObjectCallback); NSMutableDictionary *result = [NSMutableDictionary dictionary]; for (id object in self) { id key = keyFromObjectCallback(object); NSMutableArray *array = [result objectForKey:key]; if (array == nil) { array = [NSMutableArray new]; [result setObject:array forKey:key]; } [array addObject:object]; } return [result copy]; } 

Y puedes usarlo así:

 NSDictionary *groups = [people abc_groupIntoDictionary:^id(NSDictionary *person) { return person[@"groupId"]; }]; 

Esto no es exactamente lo mismo que la respuesta original, ya que conservará el diccionario de persona como los valores en la matriz, pero puede simplemente leer la propiedad del nombre fuera de eso.

Rápida implementación de la respuesta de Sergery para mis compañeros noobs.

 class People: NSObject { var groupId: String var name : String init(groupId: String, name: String){ self.groupId = groupId self.name = name } } let matt = People(groupId: "1", name: "matt") let john = People(groupId: "2", name: "john") let steve = People(groupId: "3", name: "steve") let alice = People(groupId: "4", name: "alice") let bill = People(groupId: "1", name: "bill") let bob = People(groupId: "2", name: "bob") let jack = People(groupId: "3", name: "jack") let dan = People(groupId: "4", name: "dan") let kevin = People(groupId: "1", name: "kevin") let mike = People(groupId: "2", name: "mike") let daniel = People(groupId: "3", name: "daniel") let arrayOfPeople = NSArray(objects: matt, john, steve, alice, bill, bob, jack, dan, kevin, mike, daniel) var resultArray = NSMutableArray() let groups = arrayOfPeople.valueForKeyPath("@distinctUnionOfObjects.groupId") as [String] for groupId in groups { var entry = NSMutableDictionary() entry.setObject(groupId, forKey: "groupId") let predicate = NSPredicate(format: "groupId = %@", argumentArray: [groupId]) var groupNames = arrayOfPeople.filteredArrayUsingPredicate(predicate) for i in 0.. 

Tenga en cuenta el signo @ en valueForKeyPath. eso me hizo tropezar un poco 🙂

El siguiente código Reconstruirá un NSArray agrupando los objetos con cualquier clave coincidente en cada diccionario de ese conjunto

 //only to a take unique keys. (key order should be maintained) NSMutableArray *aMutableArray = [[NSMutableArray alloc]init]; NSMutableDictionary *dictFromArray = [NSMutableDictionary dictionary]; for (NSDictionary *eachDict in arrOriginal) { //Collecting all unique key in order of initial array NSString *eachKey = [eachDict objectForKey:@"roomType"]; if (![aMutableArray containsObject:eachKey]) { [aMutableArray addObject:eachKey]; } NSMutableArray *tmp = [grouped objectForKey:key]; tmp = [dictFromArray objectForKey:eachKey]; if (!tmp) { tmp = [NSMutableArray array]; [dictFromArray setObject:tmp forKey:eachKey]; } [tmp addObject:eachDict]; } //NSLog(@"dictFromArray %@",dictFromArray); //NSLog(@"Unique Keys :: %@",aMutableArray); 

// Convertir de diccionario a array de nuevo …

 self.finalArray = [[NSMutableArray alloc]init]; for (NSString *uniqueKey in aMutableArray) { NSDictionary *aUniqueKeyDict = @{@"groupKey":uniqueKey,@"featureValues":[dictFromArray objectForKey:uniqueKey]}; [self.finalArray addObject:aUniqueKeyDict]; } 

Espero que pueda ayudar …