Best way to sort an NSArray of NSDictionary objects? - ios

I'm struggling with trying to sort an array of dictionaries.
My dictionaries have a couple of values of interest, price, popularity etc.
Any suggestions?

Use NSSortDescriptor like this..
NSSortDescriptor * descriptor = [[NSSortDescriptor alloc] initWithKey:#"interest" ascending:YES];
stories = [stories sortedArrayUsingDescriptors:#[descriptor]];
recent = [stories copy];
stories is the array you want to sort. recent is another mutable array which has sorted dictionary values. Change the #"interest" with the key value on which you have to sort.
All the best

[array sortUsingDescriptors:[NSArray arrayWithObjects:[NSSortDescriptor sortDescriptorWithKey:#"YOUR-KEY" ascending:YES], nil]];
I don't really want to break it into multiple lines. It's already simple enough for me.

You can just traverse from the parent to the required child property. For e.g.
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"parent.child.child" ascending:YES];

Update , sortUsingDescriptors is now sortedArrayUsingDescriptors
So, its like:
items = [items sortedArrayUsingDescriptors:[NSArray arrayWithObjects:descriptor,nil]];

Write a sort function that compares the relevant fields in two dictionaries. When you have this version you can for example use NSArray#sortedArrayUsingFunction:context: to sort your array.
See NSArray Class Reference

array = [array sortedArrayUsingDescriptors:[NSArray arrayWithObjects:[NSSortDescriptor sortDescriptorWithKey:#"YOUR-KEY" ascending:YES], nil]];
Remember assign to array

Related

Objective-C, Sorting an NSMultable array of type class, alphabetically?

I'm trying to sort a property on a type of a mutable array.
However I've only managed to sort a NSString array.
NSMutableArray<DBFILESFileMetadata*> *tmpArray = [[NSMutableArray alloc]init];
for (DBFILESMetadata *entry in entries)
{
//conditions
[tmpArray addObject:fileMetadata];
}
Here's the type / class
https://github.com/dropbox/dropbox-sdk-obj-c/blob/4c99bdf726cf9724adfddc19e71a87a6012eddeb/Source/ObjectiveDropboxOfficial/Shared/Generated/ApiObjects/Files/Headers/DBFILESMetadata.h
I've tried
[yourArray sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
and
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES];
[yourArray sortUsingDescriptors:[NSArray arrayWithObject:sort]];
The property is called name.
I've seen answer like this How can I sort an NSMutableArray alphabetically? but I can't seem to get this to work for my scenario.
In order to sort using sortUsingSelector you need to implement your compare method in the objects that you are trying to compare. (So your DBFILESMetadata class would need a compare method - localizedCaseInsensitiveCompare in the code above.)
You should be able too use a sort descriptor as you show in your second attempt. What happens when you do that?
A third way to do it is to use the NSMutableArray sortUsingComparator and write an NSComparator block that compares the 2 objects.
I'm out of practice with Objective-C but a quick Google search found an example, which I adapted to your specific problem:
[entries sortUsingComparator:
^NSComparisonResult(DBFILESMetadata *obj1, DBFILESMetadata *obj2)
{
return [obj1.name localizedCaseInsensitiveCompare: obj2.name];
}];
That should work, although as I say I'm out of practice in Objective-C, and its block syntax is pretty awkward and counter-intutive.

How to sort array of dictionaries by date using sort descriptor

I have an array of dictionaries where dictionary is like this.
Rows = (
"<DriverRowRecord: 0x7f8de3a240d0>",
"<DriverRowRecord: 0x7f8de3a18790>"
);
Sections = "<DriverSectionRecord: 0x7f8de3a2c5a0>";
Here DriverRowRecord and DriverSectionRecord are separate classes. In DriverSectionRecord I have a date property.
#interface DriverSectionRecord : NSObject
#property(nonatomic,retain)NSDate *date;
#end
Now I want to sort the array based on DriverSectionRecord's date property. If the dictionary contains the date key I sort it like this.
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"date" ascending:YES];
NSArray *descriptors = [NSArray arrayWithObject:descriptor];
NSArray *Ascendingorder = [Array sortedArrayUsingDescriptors:descriptors];
However, it doesn't work as date is a property of DriverSectionRecord. How can I achieve this?
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"Sections.date" ascending:YES];
NSArray *descriptors = [NSArray arrayWithObject:descriptor];
NSArray *Ascendingorder = [Array sortedArrayUsingDescriptors:descriptors];
I got he solution from above comments. Thanks to all for such a great clarification.

Need assistance regarding sorting NSMutableArray

I have an NSMutableArray and on every index I have another NSMutableArray but of different length like 2, 3, 4. I want to sort main array that the inside array who have bigger length come on top.
You can sort them using a descriptor:
NSSortDescriptor *sd = [[NSSortDescriptor alloc] initWithKey:#"count" ascending:NO];
[myArray sortUsingDescriptors:#[sd]];
The above code creates one sort descriptor on the property called "count" in descending order.
//Create a sort descriptor based on count using NSSortDescriptor class as-
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"count" ascending:NO];
//& sort your main array using sort descriptor
[mainArray sortUsingDescriptors:#[sortDescriptor]];

Sorting array of wrapper objects in iOS using NSSortDescriptor

I am trying to sort an array of UserWrapper objects. The wrapper object contains the object User, and the User object contains the property UserName (that I want to sort by).
It us easy enough to sort an array of Users (source), but the added layer of UserWrapper complicates things for me. Help please!
Here is my code, which worked for a simple User array:
NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:#"UserName"
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)] ;
NSArray *descriptors = [NSArray arrayWithObject:nameDescriptor];
NSMutableArray *contactsStartingWithKey = [nameIndexesDictionary objectForKey:aKey];
[contactsStartingWithKey sortUsingDescriptors:descriptors]; // Exception thrown here because UserName is not a property of UserWrapper, but of UserWrapper.User
The key argument of the sort descriptor can also by a key path, in your case:
[[NSSortDescriptor alloc] initWithKey:#"User.UserName"
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)] ;
Although the API and documentation of NSSortDescriptor are a bit inconsistent, the "key" parameter is actually a key path. So, you can just specify #"User.UserName" as the key and your code should work.

NSSortdescriptor not mixing lists

I've got an array which should be sorted by name, but only the half of it gets sorted. I've got a list of entries which can be devided in two parts, the first part comes from a dictionary and only has the property "name", the second part comes from a core data database and got as well the property "addedByUser". both of the lists are inside the tempArray and get added into the _resultsarray, which then directly leads to the cellForRowAtIndexPath. But before, I try to sort _resultsarray by name. Now the problem occurs: first the list without the addedByUser attribute appears (sorted by name) and then the other list (with addedByUser attribute") appears, sorted by name as well. I can't get them to be mixed.
[_resultsarray addObjectsFromArray:tempArray];
// Sort the list
NSSortDescriptor *sort2 = [NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES];
[_resultsarray sortUsingDescriptors:[NSArray arrayWithObject:sort2]];
What am I doing wrong? Thank you!
Update: I'm very sorry, I forgot to write that both tempArray and _resultsarray are mutable arrays.
Update 2: It seems like it makes a difference if the names start with an uppercase or lowercase character. My updated question is then, is there a way to sort an NSMutableArray no matter if the words start with uppercase or lowercase character?
Update 3: I found out:
NSSortDescriptor *sortByName = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES selector:#selector(caseInsensitiveCompare:)];
You should write an NSComparoator like:
_resultsarray = [tempArray sortedArrayUsingComparator:^(id firstObject, id secondObject) {
NSString *name1 = ... ; // firstObject.name or firstObject.addedByUser
NSString *name2 = ... ; // secondObject.name or secondObject.addedByUser
return [name1 compare:name2];
}];
Try this:
NSSortDescriptor *sort2 = [NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES];
_resultsarray = [tempArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort2]];

Resources