1

The title may be confusing, apologies. Maybe someone can advise me on a more appropriate title.

I have a .json file structured as below.

"sections": [{
             "title": "Locations",
             "key": "location"
             }],
"contacts": [{
             "title": "Social Worker",
             "name": "Mrs X",
             "office": "xxxxxxxx",
             "location": "Lisburn",
             "department": "xxxxxxxx",
             "telephone": "xxx xxxxxxxx"
             },...

When parsing this, I create an array called contactsArray. I can then create AEContact objects from this array like so:

    for (NSDictionary *contactDic in [contactsArray valueForKey:@"contacts"]) {
    // Create AEContact objects
    _contact = [[AEContact alloc] initWithDictionary:contactDic];
    [contacts addObject:_contact];
}
self.contacts = [contacts copy];

In the self.contacts array, the value for the contact.location property is what I am interested in. I need to create separate arrays of related AEContact objects based on the location property, then map these to the location key in my contactArray dictionary

This is what I have tried so far:

NSMutableDictionary *locationsDic = [NSMutableDictionary new];
// Loop through contacts
for (int i = 0; i < self.contacts.count; i++) {
    // Sort by location
    if ([self.contacts[i] valueForKey:@"location"] == [[[contactsArray valueForKey:@"contacts"] objectAtIndex:i] valueForKey:@"location"]) {
        [locationsDic setValue:self.contacts[i] forKey:[[[contactsArray valueForKey:@"contacts"] objectAtIndex:i] valueForKey:@"location"]];
    }
}

And the output is:

{
    Ballynahinch = "<AEContact: 0x15dda1fc0>";
    Bangor = "<AEContact: 0x15dda2210>";
    Lisburn = "<AEContact: 0x15dda1c70>";
    ...
}

When an AEContact object has the same location, it sets it as another key/value in the dictionary and overwrites the previous entry. What I need to happen is something like this:

{
    Lisburn = "<AEContact: 0x15dda18f0>",
              "<AEContact: 0x15dda18f0>",
              "<AEContact: 0x15dda18f0>";

    Bangor = "<AEContact: 0x15dda18f0>",
             "<AEContact: 0x15dda18f0>",
             "<AEContact: 0x15dda18f0>";
}

I'm not sure if the output should should/will look like the preview above, I can only assume as I have not yet achieved my goal. How can I create the related AEContact objects in an array and map them to location key in my locationsDic? Thanks.

rosshump
  • 370
  • 1
  • 4
  • 21
  • 1
    you cannot have multiple values for one key. One key and one value for a dictionary.You can have an array of values as a value to the key. – Teja Nandamuri Apr 21 '16 at 19:11
  • Ok that makes sense. Any ideas on how I can create an array of values for the key? I'm not expecting you to write a bunch of code for me, but even if you could point me in the right direction by some links? Ideally as closely related to my issue if possible. Thanks for taking the time to read. – rosshump Apr 21 '16 at 19:22
  • 1
    I'm confused by ur for loop. I think you hsould add the objects to an array here in for loop.And after the for loop ends, you can add this array to the dictionary. – Teja Nandamuri Apr 21 '16 at 19:25
  • Again, that makes sense. Thanks, it's pointed me in the right direction. Although now I just need to figure out how to sort objects based on the location property. With the change made, the dictionary adds every AEContact object to each location. Should I use some sort of predicate, or another loop to stop when it finds duplicate location values, or create separate arrays? Thanks for the help. – rosshump Apr 21 '16 at 19:38

1 Answers1

2

The title (and the problem description) are a little tough to follow, but I think you're trying to index an array of (AEContact) objects by their location parameter.

We can clarify this just with some tighter naming and with a find-or-create pattern as we process the input.

NSDictionary *jsonResult = // the dictionary you begin with
NSArray *contactParams = jsonResult[@"contacts"];
NSMutableDictionary *contactsByLocation = [@{} mutableCopy];

for (NSDictionary *contactParam in contactParams) {
    NSString *location = contactParam[@"location"];

    // here's the important part: find the array of aecontacts in our indexed result, or 
    // create it if we don't find it
    NSMutableArray *aeContacts = contactsByLocation[location];
    if (!aeContacts) {
        aeContacts = [@[] mutableCopy];
        contactsByLocation[location] = aeContacts;
    }
    AEContact *aeContact = [[AEContact alloc] initWithDictionary:contactParam];
    [aeContacts addObject:aeContact];
}

contactsByLocation will be what I think you're looking for.

danh
  • 62,181
  • 10
  • 95
  • 136
  • Many apologies about the title and description, but you were spot in in figuring out what I was trying to achieve. Your code works perfectly and exactly what I need! `contactsByLocation` is the dictionary I need. I'll study exactly how you achieved that, because it's perfect for my situation. I've been banging my head all day trying to implement this. Thanks a lot! :) – rosshump Apr 21 '16 at 20:12
  • 1
    glad to have helped. i just spotted an error in the code i suggested. please see edit. – danh Apr 21 '16 at 20:15
  • Ah yes, after a few runs I had spotted it was missing one `AEContact` object per array. I was just about to attempt to fix the error by myself, it probably would have taken me a while, so I just checked back and you're edit is working flawlessly now. Thanks again man, really appreciate the help! – rosshump Apr 21 '16 at 20:25