Reputation: 386
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
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
Reputation: 21
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
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 NSObject
s that returns the object itself).
Upvotes: 0
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