Sorting an array based on a compare model iOS - ios

Student *s1 = [Student new];
s1.city = #"Delhi";
Student *s2 = [Student new];
s2.city = #"Mumbai";
NSArray *arrModels = #[s1,s2];
NSArray *arrCompareModel = #[#"Mumbai",#"Delhi"];
I need to sort the arrModels based on arrCompareModel.
All solutions in web are related to ascending. But here I have a custom model.
How do I achieve it?

You need to write this for sorting descending
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"city" ascending:false];
NSArray *sortedArray = [arrModels sortedArrayUsingDescriptors:#[sortDescriptor]];

Try something like that:
NSArray *sortedArray = [arrModels sortedArrayUsingComparator:^NSComparisonResult(Student *obj1, Student *obj2) {
return [arrCompareModel indexOfObject:obj1.city] < [arrCompareModel indexOfObject:obj2.city];
}];

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.

Objective C custom compare: with priority

I have a NSArray of countries that I obtained using [NSLocale ISOCountryCodes]. How do I sort this NSArray such that I can put certain commonly used countries at the top of the list, while keeping the rest in its alphabetical order?
United States of America
United Kingdom
Singapore
Korea
Japan
Hong Kong
Afghanistan
Albania
Algeria
etc etc..
I am using caseInsensitiveCompare: currently to get the alphabetical order, but how can I change it such that I can specify a list to put at the top, while the rest to be kept alphabetical below.
You can delete the objects you do not want to sort,then sort the rest,then add them together.
Example Code:
NSMutableArray * allData = [[NSMutableArray alloc] initWithArray:[[NSLocale ISOCountryCodes]]];
NSArray * yourexceptArray;
[allData removeObjectsInArray:yourexceptArray];
NSMutableArray * result = [[NSMutableArray alloc] initWithArray:yourexcepArray];
sortedArray = //Sort the allData as you like,then add it to result
[result addObjectsFromArray:sortedArray]
As opposed to WenchenHuang's answer (which is valid), I think you could do it with the help of sortedArrayUsingComparator.
Inside the block just compare the strings as usually, but if the string equals to one of the codes that you want to show higher, return YES.
someArray = [someArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
if ([(NSString*)obj1 isEqualToString:#"USA"]) {
return YES;
} else if ([(NSString*)obj1 isEqualToString:#"SOME_OTHER_COUNTRY"]) {
return YES;
}
return [(NSString*)obj1 compare:(NSString*)obj2];
}];
I would do it using Sort Descriptor. I don't like manipulating array again and again. So, I find sort descriptors best in this kind of scenario. (Just personal preference)
Step 1: Create a model class with priority as a key. My model class-
#import <Foundation/Foundation.h>
#interface ISOCountry : NSObject
#property(nonatomic, strong) NSString *countryCode;
#property(nonatomic, retain) NSString *priority;
#end
Step 2: The just do this-
NSArray *ISOCountryCodes = [[NSArray alloc]initWithArray:[NSLocale ISOCountryCodes]];
NSArray *commonUsedCountries= [[NSArray alloc]initWithObjects:#"NR", #"NG", #"KW", #"ES", nil];
NSMutableArray *arrayToBeSorted = [[NSMutableArray alloc]init];
for(NSString *countryCode in ISOCountryCodes){
ISOCountry *isoCountry = [[ISOCountry alloc] init];
[isoCountry setValue:countryCode forKey:#"countryCode"];
if(![commonUsedCountries containsObject:countryCode]){
[isoCountry setValue:[NSString stringWithFormat:#"%d", 2] forKey:#"priority"];
}
else{
[isoCountry setValue:[NSString stringWithFormat:#"%d", 1] forKey:#"priority"];
}
[arrayToBeSorted addObject:isoCountry];
}
NSSortDescriptor *prioritySort = [[NSSortDescriptor alloc] initWithKey:#"priority" ascending:YES];
NSSortDescriptor *countryCodeSort = [[NSSortDescriptor alloc] initWithKey:#"countryCode" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:prioritySort, countryCodeSort, nil];
NSArray *sortedArray = [arrayToBeSorted sortedArrayUsingDescriptors:sortDescriptors];

How to Modify this NSMutableArray?

I have a dictionary which contain this data:
(
contact={name="Lion",id="1",photo="simba.png",address="elm street"},
{name="Cat",id="2",photo="halleberry.png",address="attic"},
{name="Bat",id="3",photo="dracule.jpg",address="long way home baby"}
)
From that NSDictionary, i grab only the name and sorted it alphabetically. Like this:
(B={"Bat"}, C={"Cat"}, L={"Lion"})
This is the code i used:
NSMutableDictionary* sortedDict = [NSMutableDictionary dictionary];
for (NSDictionary* animal in dataDict[#"user"]){
NSString* name = animal[#"name"];
if (![name length])
continue;
NSRange range = [name rangeOfComposedCharacterSequenceAtIndex:0];
NSString* key = [[name substringWithRange:range] uppercaseString];
NSMutableArray* list = sortedDict[key];
if (!list){
list = [NSMutableArray array];
[sortedDict setObject:list forKey:key];
}
[list addObject:name];
Then, what i want to ask is. What i need to create an array of photos but sorted alphabetically based on the name. I mean something like this:
(B="dracule.jpg", C="halleberry.png"...etc)
I also heard that this will be more effective to use (B={name="Bat", photo="draggle.jpg"}) but don't know how i can make something like this and don't know how to call it separately. Please i need your help :"(
You can easily sort the array which contains dictionaries values, see below
//Get the contact array.
NSArray *contacts=[dic objectForKey:#"contact"];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
NSArray *sortedArray = [contacts sortedArrayUsingDescriptors:#[sortDescriptor]];
I hope it helps.

Sorting array using NSSortDescriptor is not working

I have an array with multiple dictionary like:
{
highRate = "600.49";
hotelId = 439607;
hotelRating = "2.5";
latitude = "12.97153";
longitude = "80.15096";
lowRate = "600.49";
name = "Hotel Kingss Park";
proximityDistance = "17.999475";
thumbNailUrl = "http://images.travelnow.com/hotels/7000000/6510000/6500300/6500296/6500296_3_t.jpg";
tripAdvisorRating = "4.0";
},
{
highRate = "990.0";
hotelId = 327929;
hotelRating = "2.0";
latitude = "13.06931";
longitude = "80.2706";
lowRate = "450.45";
name = "Mallika Residency";
proximityDistance = "1.6274245";
thumbNailUrl = "http://images.travelnow.com/hotels/3000000/2960000/2958400/2958303/2958303_2_t.jpg";
tripAdvisorRating = "2.5";
}
I try to sort this array using lowRate key.
NSSortDescriptor *rating_Sort = [NSSortDescriptor sortDescriptorWithKey:#"lowRate" ascending:NO];
NSArray *descriptorArray = [NSArray arrayWithObject:rating_Sort];
NSArray *sortedArray = [self.tblDisplayArray sortedArrayUsingDescriptors:descriptorArray];
here self.tblDisplayArray is my array.
But not getting proper sorted array in Result.
Why this happen?
They are all strings so it is attempting to sort them alphabetically not numerically. Try either:
NSSortDescriptor *desc = [[NSSortDescriptor alloc]initWithKey:#"doubleValue" ascending:YES];
or using NSNumbers instead of NSString... #() instead of #"".
#Rajesh is correct, not all your numbers are integers so you should be using doubleValue, I have updated the code!
Hope this helps! :)
change this
NSSortDescriptor *rating_Sort = [NSSortDescriptor sortDescriptorWithKey:#"lowRate.doubleValue" ascending:NO];
and it's working fine.
As #Georgegreen pointed they are all strings so it is attempting to sort them alphabetically not numerically.
but you should be using float or double to be precise instead of int.
NSSortDescriptor *desc = [[NSSortDescriptor alloc]initWithKey:#"doubleValue" ascending:YES];
Or just do:
NSArray *sortedArray = [[yourTempArray sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
You've array of string which is actually double value. So you sort descriptors as below.
NSSortDescriptor *aSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"sort" ascending:YES comparator:^(id obj1, id obj2) {
if ([obj1 doubleValue] < [obj2 doubleValue]) {
return (NSComparisonResult)NSOrderedAscending;
}
return (NSComparisonResult)NSOrderedSame;
}];
sortedArray = [yourArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:aSortDescriptor]];

Resources