Silversnail
Silversnail

Reputation: 386

Sort an NSArray with NSDictionary

I'm using NSSortDiscriptors to sort an NSArray. Every index in the array contains a dictionary with key,value entries. This dictionary also holds another dictionary.

My problem that I want solve is to sort the array based on values on the first dictionary, but also on some values in the dictionary it contains.

The following is the sort method I use for the other values in the array.

- (void)sortArray {

if ([array count] != 0) {

    // Reports sortingDescriptors
    NSSortDescriptor * city = [[NSSortDescriptor alloc] initWithKey:@"City" ascending:YES];
    NSSortDescriptor * name = [[NSSortDescriptor alloc] initWithKey:@"Name" ascending:YES];
    NSSortDescriptor * country = [[NSSortDescriptor alloc] initWithKey:@"Country" ascending:YES];

    [reportsArray sortUsingDescriptors:[NSArray arrayWithObjects:city, name, country, nil]];

    [name release];
    [city release];
    [country release];
}
}

The array looks like this:

[{name = "";
city = "";
country = "";
date = {
 dateAdded = "";
 dateRemoved = "";
}
}];

So I also want to sort on, if have value on dateAdded for example.

Upvotes: 1

Views: 2020

Answers (4)

JustSid
JustSid

Reputation: 25318

You can specify a key path when you create the NSSortDescriptor, this way you can sort the NSArray with a NSDictionary.

Upvotes: 1

NSArray *unsortedArray=[NSArray arrayWithObjects:[NSDictionary dictionaryWithObjectsAndKeys:@"anil",@"personInDictionary.lastName" ,nil],[NSDictionary dictionaryWithObjectsAndKeys:@"aneelu",@"personInDictionary.lastName", nil] ,[NSDictionary dictionaryWithObjectsAndKeys:@"kumar",@"anil.lastName", nil] ,nil];

 NSSortDescriptor * descriptor = [[[NSSortDescriptor alloc] initWithKey:@"personInDictionary.lastName"             ascending:YES] autorelease]; // 1

  NSArray * sortedArray = [unsortedArray sortedArrayUsingDescriptors:
                             [NSArray arrayWithObject:descriptor]];

 NSLog(@"sortedArray values %@",sortedArray);

  for (id object in [sortedArray valueForKey:@"personInDictionary.lastName"]) {

        NSLog(@"sortedArray value %@",object);
    }

Upvotes: 0

JeremyP
JeremyP

Reputation: 86651

Are you saying that the objects in the array have a City, Name and Country property but also a dictionary property and you want to sort on one of the keys in the dictionary? Or are you saying that the entries in the array are dictionaries but sometimes the City, Name or Country key is missing? Or are you saying that some of the entries are dictionaries and some are objects with the listed properties?

In any case, you can get more flexibility by creating a sort descriptor using initWithKey:ascending:comparator:. This allows you to supply a comparator block as the sort function which is more flexible than a straight selector e.g.

NSComparator mySort = ^(id obj1, id obj2)
{
    NSComparisonResult ret = NSOrderedSame;

    if ([obj1 isKindOfClass: [NSDictionary class]] && ![obj2 isKindOfClass: NSDictionary class]])
    {
        ret = NSOrderedAscending;
    }
    else if (![obj1 isKindOfClass: [NSDictionary class]] && [obj2 isKindOfClass: NSDictionary class]])
    {
        ret = NSOrderedDescending;
    }
    return ret;
};
NSSortDescriptor* descriptor = [[NSSortDescriptor alloc] initWithKey: @"self" ascending: YES comparator: mySort];

will give you a sort descriptor that sorts the array putting all the NSDictionaries first and other objects afterwards. (self is a key possessed by all NSObjects that returns the object itself).

Upvotes: 0

user756245
user756245

Reputation:

You might want to check if the dictionary contains a value like that :

// you can't set nil as a value for a key
if([yourDictionary objectForKey:@"yourKey"] == [NSNull null]) { ... }

Then you need to sort remaining objects but the dictionary, to do so, make a copy of your array without the dictionary entry by doing something like :

NSMutableArray *tmpArray = [NSMutableArray arrayWithArray:firstArray];
[tmpArray removeObjectAtIndex:theIndexOfTheDictionary];
// sort your array, don't forget to catch the returned value
NSMutableArray *sortedArray = [tmpArray sortUsingDescriptors:[NSArray arrayWithObjects:city, name, country, nil]];
// finally, put the dictionary back in (if needed)
[sortedArray insertObject:theDictionary atIndex:theIndexYouWant];

Upvotes: 0

Related Questions