Rebuild an NSArray by grouping objects that have matching id numbers?

前端 未结 5 1229
醉酒成梦
醉酒成梦 2020-11-29 06:38

I have an NSArray and each object in the array has a groupId and a name. Each object is unique but there are many with the same groupId. Is there a way i can tear the arra

相关标签:
5条回答
  • 2020-11-29 07:20

    This is similar to Seva's answer, but it can be added as a category method on NSArray:

    /// @return A dictionary of NSMutableArrays
    - (NSDictionary *)abc_groupIntoDictionary:(id<NSCopying>(^)(id object))keyFromObjectCallback {
        NSParameterAssert(keyFromObjectCallback);
        NSMutableDictionary *result = [NSMutableDictionary dictionary];
        for (id object in self) {
            id<NSCopying> 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];
    }
    

    And you can use it like so:

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

    This isn't exactly the same as the original answer since it will preserve the person dictionary as the values in the array, but you can then just read the name property off of that.

    0 讨论(0)
  • 2020-11-29 07:26

    Swift implementation of Sergery's answer for my fellow 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..<groupNames.count {
            let people = groupNames[i] as People
            let name = people.name
            entry.setObject(name, forKey: ("name\(i)"))
        }
        resultArray.addObject(entry)
    }
    
    println(resultArray)
    

    Note the @ sign in valueForKeyPath. that tripped me up a little :)

    0 讨论(0)
  • 2020-11-29 07:30

    This calls for a NSDictionary of NSArrays. There's no quick and elegant way - you'd have to scroll through the source.

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

    EDIT: edited to not assume the datatype of the key.

    0 讨论(0)
  • 2020-11-29 07:33
    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);
    

    Output:

        (
            {
            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;
        }
     )
    
    0 讨论(0)
  • 2020-11-29 07:36

    The below code will Rebuild an NSArray by grouping objects w.r.t any matching keys in each dictionary in that array

    //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);
    

    //Converting from dictionary to array again...

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

    Hope it may help..

    0 讨论(0)
提交回复
热议问题