Objective C - How do I convert this NSArray to an NSDictionary so I can look up city names by zip code?

958 views Asked by At

I use Parse as my backend, and have a cloud function (written in javascript) that just returns an array

var providerZIPToCity = [ {zip:"48393", city:"WIXOM, MI"},{zip:"48116", city:"48116, MI"},{zip:"48114", city:"BRIGHTON, MI"},{zip:"48189", city:"WHITEMORE LAKE, MI"},{zip:"48178", city:"SOUTH LYON, MI"},{zip:"48168", city:"NORTHVILLE, MI"},{zip:"48167", city:"NORTHVILLE, MI"},{zip:"48375", city:"NOVI, MI"},{zip:"48374", city:"NOVI, MI"},{zip:"48165", city:"NEW HUDSON, MI"},{zip:"48377", city:"NOVI, MI"},{zip:"48390", city:"WALLED LAKE, MI"},{zip:"48381", city:"MILFORD, MI"},{zip:"48226", city:"DETROIT, MI"},{zip:"48201", city:"DETROIT, MI"}];

When I return this and print it out using the following objective c code in my app, I get the results below:

[PFCloud callFunctionInBackground:@"zipToCity" withParameters:@{} block:^(NSArray *results, NSError *error)
{
    [_activityIndicator stopAnimating];
    if( !error )
    {
        NSLog(@"%@",results);
    }
    else
    {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"CITY LOOKUP FAILED" message:@"We've failed to look up the city names for these ZIP codes.  Try reloading this page from the menu. If the problem persists, you may not have a data or Wi-Fi connection." delegate:self  cancelButtonTitle:@"OK" otherButtonTitles: nil];
        alert.tag = 0;
        [alert show];
    }
}];

returns:

2015-06-10 17:25:04.444 XXXXXXXXX[266:18098] (
        {
        city = "WIXOM, MI";
        zip = 48393;
    },
        {
        city = "48116, MI";
        zip = 48116;
    },
        {
        city = "BRIGHTON, MI";
        zip = 48114;
    },
        {
        city = "WHITEMORE LAKE, MI";
        zip = 48189;
    },
        {
        city = "SOUTH LYON, MI";
        zip = 48178;
    },
        {
        city = "NORTHVILLE, MI";
        zip = 48168;
    },
        {
        city = "NORTHVILLE, MI";
        zip = 48167;
    },
        {
        city = "NOVI, MI";
        zip = 48375;
    },
        {
        city = "NOVI, MI";
        zip = 48374;
    },
        {
        city = "NEW HUDSON, MI";
        zip = 48165;
    },
        {
        city = "NOVI, MI";
        zip = 48377;
    },
        {
        city = "WALLED LAKE, MI";
        zip = 48390;
    },
        {
        city = "MILFORD, MI";
        zip = 48381;
    },
        {
        city = "DETROIT, MI";
        zip = 48226;
    },
        {
        city = "DETROIT, MI";
        zip = 48201;
    }
)

I have a bunch of labels that contain various zip codes that I need to iterate through, and change a label next to the zip code to be the city name associated with that zip code. I need to use that array, results,to either build an NSDictionary, or somehow access those city names by zip code from the current set up.

Problem is, I'm a bit of an objective C noob and I'm not entirely sure how this data is stored in the array. What type are the objects in this NSArray? They don't appear to be dictionaries to me. I'm a bit stumped, just not familiar with the data type enough to figure out how to do the lookup I need.

Could anyone point me in the right direction for how I could either create an NSMutableDictionary, which I do know how to look up values (city name strings) by keys ( zip codes ), or how I can iterate through my zip code labels and look up the city names directly with this NSArray?

I'm picturing either

NSMutableDictionary *ZIPsToCitiesDictionary = [NSMutableDictionary new];
for( int i = 0; i < [results count]; i++ )
{
    //get element, i.e. ( {city = "WIXOM, MI"; zip = 48393;} )
    //create new NSMutableDictionary element
    [ZIPsToCitiesDictionary setObject: <city> forKey: <zip>];
}

then I can use the label.text parameter to access the city names,

or:

NSArray *ZIPLabelArray = ...;
NSMutableArray cityLabelArray = [NSMutableArray new]; //indexes correspond with ZIPLabelArray indexes

for( int i = 0; i < [ZIPLabelArray count]; i++ )
{
    [cityLabelArray addObject: <city name somehow extracted from results by looking up the zip code at ZIPLabelArray[i]> ];
}

I appreciate any tips.

2

There are 2 answers

3
Ken Thomases On BEST ANSWER

The elements of your array are indeed dictionaries. To test this, you can do something like:

NSLog(@"%@", NSStringFromClass(results[0]));

You were very close. You could do:

NSMutableDictionary *ZIPsToCitiesDictionary = [NSMutableDictionary new];
for(NSDictionary* dict in results)
{
    NSString* city = dict[@"city"];
    NSString* zip = dict[@"zip"];
    [ZIPsToCitiesDictionary setObject:city forKey:zip]; // or ZIPsToCitiesDictionary[zip] = city
}

Update to account for multiple cities sharing the same zip:

NSMutableDictionary *ZIPsToCitiesDictionary = [NSMutableDictionary new];
for(NSDictionary* dict in results)
{
    NSString* city = dict[@"city"];
    NSString* zip = dict[@"zip"];
    NSMutableArray* citiesForZip = ZIPsToCitiesDictionary[zip];
    if (!citiesForZip)
    {
        citiesForZip = [NSMutableArray new];
        ZIPsToCitiesDictionary[zip] = citiesForZip;
    }
    [citiesForZip addObject:city];
}

This will produce a dictionary mapping a zip code to an array of cities.

1
Rog On

A more succinct way

    NSArray *filteredByZip = [results filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"zip == '48393'"]];

This will return an array of items that match the condition zip == 48393.