Sodbileg Gansukh
Sodbileg Gansukh

Reputation: 1740

NSArray and NSDictionary

I have NSDictionaries in NSArray just like below.

array(dictionary("user":1, "p1":1), dictionary("user":2, "p1":3), dictionary("user":1, "p1":5), dictionary("user":2, "p1":7))

And I want to turn this array into dictionary like below.

NSArray *u1 = [NSArray arrayWithObjects:@"1", @"5", nil];
NSArray *u2 = [NSArray arrayWithObjects:@"3", @"7", nil];
keys = [NSArray arrayWithObjects:@"u1", @"u2", nil];
points = [NSDictionary dictionaryWithObjectsAndKeys:u1, @"u1", u2, @"u2", nil];

How can I do that? I am lost, can you guys please help me?

Upvotes: 0

Views: 472

Answers (5)

CRD
CRD

Reputation: 53010

What have you tried?

Here is some code typed directly into the answer, so it has not be tested:

You haven't given a name for your original array, so let's assume it is:

NSArray *originalArray;

We need a mutable dictionary to store the result:

NSMutableDictionary *points = [NSMutableDictionary new];

Now we need to process every element in the original array and it is a dictionary:

for(NSDictionary *item in originalArray)
{

Get the current entry in points array that matches item. You don't give types for your entries, so we'll use id:

   id currentUser = [item objectForKey:@"user"];
   NSMutableArray *currentValues = [points objectForKey:currentUser];

If this is the first occurrence of currentUser then currentValues will be nil, and we need to create an array for the p1 value and add it to points:

   if (currentValues == nil)
      [points addObject:[NSMutableArray arrayWithObject:[item objectForKey:@"p1"]
                                                 forKey:currentUser
                        ]
      ]

Otherwise we just add the p1 value to the array:

   else
      [currentValues setObject:[item objectForKey:@"p1"]];

close out the loop and get the keys:

}

NSArray *keys = [points allKeys];

Now if you're using Xcode 4.5 you can use modern syntax for some of that:

NSMutableDictionary *points = [NSMutableDictionary new];
for(NSDictionary *item in originalArray)
{
   id currentUser = item[@"user"];
   NSMutableArray *currentValues = points[currentUser];
   if (currentValues == nil)
      points[currentUser] = [NSMutableArray arrayWithObject:item[@"p1"];
   else
      [currentValues addObject:item[@"p1"]];
}
NSArray *keys = [points allKeys];

HTH

Upvotes: 1

Rob
Rob

Reputation: 438467

Tons of approaches. Here's another:

NSArray *originalArray = @[
    @{@"user":@"u1", @"p1":@"1"},
    @{@"user":@"u2", @"p1":@"3"},
    @{@"user":@"u1", @"p1":@"5"},
    @{@"user":@"u2", @"p1":@"7"}
];

NSLog(@"originalArray = %@", originalArray);

NSMutableDictionary *results = [NSMutableDictionary dictionary];

for (NSDictionary *dictionary in originalArray) {
    NSString *user = dictionary[@"user"];
    NSString *p1   = dictionary[@"p1"];

    if (!results[user])
        results[user] = [NSMutableArray array];

    [results[user] addObject:p1];
}

NSLog(@"results = %@", results);

That takes:

originalArray = (
        {
        p1 = 1;
        user = u1;
    },
        {
        p1 = 3;
        user = u2;
    },
        {
        p1 = 5;
        user = u1;
    },
        {
        p1 = 7;
        user = u2;
    }
)

And gives

results = {
    u1 =     (
        1,
        5
    );
    u2 =     (
        3,
        7
    );
}

Upvotes: 0

Martin R
Martin R

Reputation: 540125

Another possible solution (works with an arbitrary number of users):

NSArray *orig = @[
    @{@"user" : @"1", @"p1" : @"1"},
    @{@"user" : @"2", @"p1" : @"3"},
    @{@"user" : @"1", @"p1" : @"5"},
    @{@"user" : @"2", @"p1" : @"7"},
];

// Create set of all users (without duplicates)
NSSet *users = [NSSet setWithArray:[orig valueForKey:@"user"]];

NSMutableDictionary *points = [NSMutableDictionary dictionary];
for (NSString *user in users) {
    // newKey = "u" + username, e.g. "u1" or "u2":
    NSString *newKey = [@"u" stringByAppendingString:user];

    // newValue = array of "p1" values of the current user:
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"user == %@", user];
    NSArray *newValue = [[orig filteredArrayUsingPredicate:pred] valueForKey:@"p1"];

    // Add to dictionary:
    [points setObject:newValue forKey:newKey];
}
NSLog(@"%@", points);

Output:

{
    u1 =     (
        1,
        5
    );
    u2 =     (
        3,
        7
    );
}

And the keys can be obtained by

NSArray *keys = [points allKeys];

Upvotes: 0

Anoop Vaidya
Anoop Vaidya

Reputation: 46563

You can do, like this (code not tested)

NSMutableArray *keys=[NSMutableArray new];
NSMutableArray *u1=[NSMutableArray new]; 
NSMutableArray *u2=[NSMutableArray new];
NSMutableDictionary  *points=[NSMutableDictionary new];

for (id dict in array){
    NSString *user=[dict objectForKey:@"user"];
    NSString *p1=[dict objectForKey:@"p1"];
    [keys addObject:[NSString stringWithFormat:@"%@",user]];
    if( [user isEqualToString:@"1"] ){
        [u1 addObject:user];
    }
    else{
        [u2 addObject:user];
    }
}

points=[NSDictionary dictionaryWithObjectsAndKeys:u1,@"u1",u2, @"u2", nil];

Upvotes: 0

LighteningKid
LighteningKid

Reputation: 172

Couldn't you just iterate over your original array, asking each dictionary if the object for key "user" is 1, and if so, copy the object into a new array at index 0? Or if your user numbers are in counting order, maybe even have the index number equal the user number. Then repeat for "user" = 2, etc. Then make a dictionary so that each key/object pair is created by keys from the keys array (keys[i]) and objects from your new array (objects[i]).

Upvotes: 2

Related Questions