Sort on string and float not working - ios

I have name and distance fields in an array of data that I want to sort; I can sort by either one but not both together. I want the data sorted by name first, then distance, but when I use the two together, the sort is always on the first descriptor in the list, the second seems to get ignored.
NSSortDescriptor *nameSort = [[NSSortDescriptor alloc]
initWithKey:#"NAME"
ascending:YES
selector:#selector(localizedStandardCompare:)];
NSSortDescriptor *distanceSort = [[NSSortDescriptor alloc]
initWithKey:#"DISTANCE"
ascending:YES];
sortedArray = [featureSet.features sortedArrayUsingDescriptors:#[nameSort, distanceSort]];
[super.tableView reloadData];

The behavior you're seeing definitely makes sense - "A&W #0338" comes before "A&W #0339", so there is nothing more for the distance sort to determine.
If all of your data is structured this way - a name followed by #000 - you can strip the numbers off for your sort, and then your distance sort can do its job. You can either do that at the model layer by splitting your title into two properties, a name and location number, or you can do it inside of a sort descriptor.
NSSortDescriptor *nameSort = [NSSortDescriptor sortDescriptorWithKey:#"title" ascending:YES comparator:^NSComparisonResult(NSString *str1, NSString *str2) {
NSString *title1 = [[str1 componentsSeparatedByString:#" #"] firstObject];
NSString *title2 = [[str2 componentsSeparatedByString:#" #"] firstObject];
return [title1 compare:title2];
}];
If you use this nameSort and your distanceSort, "A&W #0338", "25 km" will come after "A&W #0339"

Related

Use Two NSSortDescriptor to filter array

I would like to sort an array using the dictionary values "Name" and "Count". It would be Name alphabetically and split the names up into two groupd based on count.
bigger than 0
Smaller than Equal 0
My current implementation looks like this however it dose not split the groups up correctly.
NSSortDescriptor *sortCountDescriptor = [[NSSortDescriptor alloc] initWithKey:#"count" ascending:NO];
NSSortDescriptor *sortNameDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
NSArray * sortDescriptors = [NSArray arrayWithObjects:sortCountDescriptor, sortNameDescriptor, nil];
NSArray *sortedArray = [myArrayToSort sortedArrayUsingDescriptors:sortDescriptors];
return [sortedArray mutableCopy];
If by grouping you mean making them separate arrays then you need an NSPredicate instead of NSSortDescriptor for count key.
Try this (from what I understood the array is filled with instances of NSDictionary so I used casting to it. If that assumption is incorrect, the NSPredicate isn't hard to change to some other type or to be made more generic with KVC):
NSSortDescriptor *sortNameDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:NO];
NSArray * sortDescriptors = [NSArray arrayWithObjects:sortNameDescriptor, nil];
NSArray *sortedArray = [myArrayToSort sortedArrayUsingDescriptors:#[sortNameDescriptor]];
NSPredicate *zeroOrLessPredicate = [NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
if ([[((NSDictionary*)evaluatedObject) objectForKey:#"count"] integerValue] <= 0) {
return YES;
}
else {
return NO;
}
}];
NSArray *zeroOrLessArray = [sortedArray filteredArrayUsingPredicate:zeroOrLessPredicate];
NSPredicate *moreThanZeroPredicate = [NSCompoundPredicate notPredicateWithSubpredicate:zeroOrLessPredicate];
NSArray *moreThanZeroArray = [sortedArray filteredArrayUsingPredicate:moreThanZeroPredicate];

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.

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]];

NSSortDescriptor sort a string field as a number with comparator block not working

I have a field full of ids from a third party. The ids are numbers but written to the db as a string.
I want to sort a fetch sorted by this id on the value of the integer. So I'm adding this NSSortDescriptor to the NSFetchRequest.
NSNumberFormatter *numFormatter = [[NSNumberFormatter alloc] init];
[numFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSSortDescriptor *sortBy = [[NSSortDescriptor alloc] initWithKey:#"someId" ascending:YES comparator:^(id a, id b) {
return [[numFormatter numberFromString:a] compare:[numFormatter numberFromString:b]];
}];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortBy]];
But I get results like the the following. These are still sorted as a string, alphabetically.
730275292
73900038
730172867
7350727
830138437
835164
837287901
8338804
930274
9324376
What am I not understanding about using this comparator block?
EDIT May 1 2012 9:20 AM EST
To test whether the comparator block is being used, I tried the following to sort based on the length of the field.
NSSortDescriptor *sortBy = [[NSSortDescriptor alloc] initWithKey:#"fbId" ascending:YES comparator:^(id a, id b) {
if ([a length] < [b length]) {
return NSOrderedAscending;
} else if ([a length] > [b length]) {
return NSOrderedDescending;
} else {
return NSOrderedSame;
}
}];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortBy]];
I'm still getting results sorted by the alphabetically order! So this makes me think the comparator block is not even being used.
716164250
726354466
73900038
739600038
7450727
810138437
801164
801375346
8213997
Try this !
[NSSortDescriptor sortDescriptorWithKey:#"name"
ascending:YES
selector:#selector(localizedStandardCompare:)]
I don't use NSFetchRequest so I can't comment on that specifically, but it appears to be something related to it. The code you use in your comparator block is just fine. I setup an array of the exact numbers you show and then sorted them using your code and everything worked out fine:
NSArray *array = [NSArray arrayWithObjects:#"730275292",
#"73900038",
#"730172867",
#"7350727",
#"830138437",
#"835164",
#"837287901",
#"8338804",
#"930274",
#"9324376", nil];
NSNumberFormatter *numFormatter = [[NSNumberFormatter alloc] init];
[numFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSArray *sArray = [array sortedArrayUsingComparator:^(id a, id b) {
return [[numFormatter numberFromString:a] compare:[numFormatter numberFromString:b]];
}];
NSLog(#"%#",sArray);
When the above code runs, I get a log of:
(
835164,
930274,
7350727,
8338804,
9324376,
73900038,
730172867,
730275292,
830138437,
837287901
)
I believe this is the order you're looking for. You might consider taking the results of your fetch request and sorting them in an array after you've received them. I doubt it matters whether an array does the sorting or the fetch request does the sorting. Most likely there's no performance gain of using one over the other.
If you still want NSFetchRequest to do the sorting, then there might be something your missing in order to get it to sort properly. Honestly, I'm not sure since I've not used it.
UPDATE
Quickly looking through the NSFetchRequest docs, I've found that there are some parameters that affect sorting. For example, in the docs for the resultType it gives this message:
You use setResultType: to set the instance type of objects returned
from executing the request—for possible values, see
“NSFetchRequestResultType.” If you set the value to
NSManagedObjectIDResultType, this will demote any sort orderings to
“best efforts” hints if you do not include the property values in the
request.
So it looks as though the return type might be affecting your sorting.

Best way to sort an NSArray of NSDictionary objects?

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

Resources