How to sort a NSMutableArray using NSSortDescriptor? - iphone

I'm parsing data from JSON webservice and then using the following code to sort the data by price, date, discount etc.
here's the code I'm using to sort the data:
-(void)priceSort:(id)sender {
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
initWithKey: #"price" ascending: YES];
NSMutableArray *sortedArray = (NSMutableArray *)[self.displayItems
sortedArrayUsingDescriptors: [NSArray arrayWithObject:sortDescriptor]];
[self setDisplayItems:sortedArray];
[self.tableView reloadData];
}
this works fine when I'm trying to sort by price, however when I want to sort by number of reviews I can't seem to get the code right:
for price I use:
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
initWithKey: #"price" ascending: YES];
but for reviews I want to get the "n" value. see how it's nested in the output (of the display Items mutableArray below:
"old_price" = 24;
price = "9.9";
reviews = {
**n = 11;**
val = 70;
};
"sold_count" = 101;
thanks for any help on this :)

To sort by the number of reviews n, your sort descriptor would be:
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
initWithKey: #"reviews.n" ascending: YES];

Related

CKQueryOperation get the last record

I need to fetch the very last record in cloudkit. Here is my code:
CKContainer *container = [CKContainer containerWithIdentifier:containerID];
CKDatabase *publicDatabase = [container publicCloudDatabase];
CKQuery *query = [[CKQuery alloc] initWithRecordType:recordType
predicate:[NSPredicate predicateWithFormat:#"TRUEPREDICATE"]];
CKQueryOperation *queryOp = [[CKQueryOperation alloc] initWithQuery:query];
queryOp.desiredKeys = #[#"record.recordID.recordName"];
queryOp.recordFetchedBlock = ^(CKRecord *record)
{
//do something
};
queryOp.queryCompletionBlock = ^(CKQueryCursor *cursor, NSError *error)
{
NSLog(#"CKQueryCursor error %#", error);
};
queryOp.resultsLimit = CKQueryOperationMaximumResults;
[publicDatabase addOperation:queryOp];
My question is how can I modify my code to get the very last record in cloudkit?
I'll really appreciate your help
You can sort on the creation dat ascending and then just ask for 1 result like this (code is in Swift):
Adding the sort:
query.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
Limiting the result:
queryOp.resultsLimit = 1
Objective-C version
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"creationDate" ascending:NO];
query.sortDescriptors = #[sortDescriptor];
for one record:
queryOp.resultsLimit = 1;
Setting resultsLimit does not seem to work for me, however set it anyway and sorting the results using a timestamp or the record creation date. Then store the results in an array and simply use the first or last item depending on the sort order
CKContainer *container = [CKContainer containerWithIdentifier:containerID];
CKDatabase *publicDatabase = [container publicCloudDatabase];
CKQuery *query = [[CKQuery alloc] initWithRecordType:recordType predicate:[NSPredicate predicateWithFormat:#"TRUEPREDICATE"]];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"creationDate" ascending:NO];
query.sortDescriptors = #[sortDescriptor];
CKQueryOperation *queryOp = [[CKQueryOperation alloc] initWithQuery:query];
queryOp.desiredKeys = #[#"record.recordID.recordName"];
queryOp.recordFetchedBlock = ^(CKRecord *record)
{
//do something
recordArray.append(record)
};
queryOp.queryCompletionBlock = ^(CKQueryCursor *cursor, NSError *error)
{
NSLog(#"CKQueryCursor error %#", error);
let myLastRecord = recordArray[recordArray.count - 1]
};
queryOp.resultsLimit = CKQueryOperationMaximumResults;
[publicDatabase addOperation:queryOp];

Does NSSortDescriptor can sort array with DateTime type?

Here is my code:
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"inspectionDateTime"
ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
sortedArray = [listAllProject sortedArrayUsingDescriptors:sortDescriptors];
[sortedArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2)
{
UDS_ProjectField *projectField1 = obj1;
UDS_ProjectField *projectField2 = obj2;
return [projectField1.inspectionDateTime compare:projectField2.inspectionDateTime];
return YES;
}];
I use this to sort an array of a table in database which has field name "inspectionDateTime"
type DATETIME, but the result is not correct.
This is the result
15/2/12
15/1/12
12/3/12
but expecting result is
12/3/12
15/2/12
15/1/12
So the question is NSSortDescriptor can sort DateTime type, if not please show me another way
NSSortDescriptor can be used to date sorting, I used following code and it is working for me:
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey::#"inspectionDateTime"
ascending:YES selector:#selector(compare:)];
[listAllProject sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
try this
NSArray *sortedArray = [listAllProject sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2)
{
UDS_ProjectField *projectField1 = obj1;
UDS_ProjectField *projectField2 = obj2;
return [projectField1.inspectionDateTime compare:projectField2.inspectionDateTime];
return YES;
}];
For more you can read docs here

Sort NSArray with multiple NSDictonaries in it [duplicate]

This question already has answers here:
Sorting NSArray of dictionaries by value of a key in the dictionaries
(11 answers)
Closed 9 years ago.
I need to sort the given "document" array with "lastname". Here is the sample json
document [
{
id:"100"
person :{
name : {
firstname : "xyz",
lastname : "oops"
},
photourl: "photo-url"
}
},
{
id:"200"
person :{
name : {
firstname : "xyz",
lastname : "oops"
},
photourl: "photo-url"
}
}]
it has an dict "name" inside one more dict "person" and we need to sort with lastname first n then with lastname
NSSortDescriptor *lastNameDescriptor = [[NSSortDescriptor alloc] initWithKey:#"lastname " ascending:YES] ;
NSArray *sortedArray = [NSArray arrayWithObject:lastNameDescriptor];
sortedArray = [myArray sortedArrayUsingDescriptors:sortDescriptors];
for more clear description and code check this link, its very easy and perfect, Cheers :)
Use the below given logic
for (NSMutableDictionary *document in documents) {
NSString *lastName = [[document valueForKey:#"person"] valueForKey:#"lastname"];
[documents setObject:lastName forKey:#"lastnameDescriptor"];
}
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"lastnameDescriptor" ascending:YES];
NSMutableArray *sortedNames = [documents sortedArrayUsingDescriptors:[NSArray arrayWithObject:descriptor]];
for (NSMutableDictionary *document in sortedNames) {
[document removeObjectForKey:#"lastnameDescriptor"];
}
The other answers are close but either needlessly complicated or a little off.
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:#"person.lastName" ascending:YES];
sortedArray = [document sortedArrayUSingDescriptors:#[descriptor]];
(The selector says "key," but if you read the docs, it's actually a keypath, so this will work as expected.)
Lots of almost right answers but none that consider that 'name' is itself a nested dictionary in your document. So I think what you want is:
NSSortDescriptor *lastNameDescriptor = [NSSortDescriptor sortDescriptorWithkey:#"person.name.lastname" ascending:YES];
NSSortDescriptor *firstNameDescriptor = [NSSorteDescriptor sortDescriptorWithKey:#"person.name.firstname" ascending:YES];
NSArray *sortedArray = [document sortedArrayUsingDescriptors:#[lastNameDescriptor, firstNameDescriptor]];
So assuming you put your JSON into an array called "people":
NSArray *people = myArrayFromJSON;
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"person" ascending:YES comparator:^NSComparisonResult(id obj1, id obj2) {
NSString *lastName1 = [obj1 valueForKey:#"lastname"];
NSString *lastname2 = [obj2 valueForKey:#"lastname"];
return [lastName1 compare:lastname2];
}];
NSArray *sortedArray = [people sortedArrayUsingDescriptors:#[sortDescriptor]];
That'll do it.

Sort an array using array index

I am stuck here......
I have two arrays Arr_title and Arr_distance
I get sorted Arr_distance using this method
NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"self" ascending:YES]autorelease];
sortedFloats = [appDel.Arr_distance sortedArrayUsingDescriptors:
[NSArray arrayWithObject:sortDescriptor]];
but problem is that i want to sort Arr_title according to index of sortedFloats array...
thx in advance for help me..........
Try this,
NSDictionary *dict = [NSDictionary dictionaryWithObjects:Arr_title forKeys:Arr_distance];
NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"self" ascending:YES] autorelease];
sortedFloats = [appDel.Arr_distance sortedArrayUsingDescriptors:
[NSArray arrayWithObject:sortDescriptor]];
NSMutableArray *sortedTitles = [NSMutableArray array];
for (NSString *key in sortedFloats) {//or just use sortedTitles = [dict objectsForKeys:sortedFloats notFoundMarker:[NSNull null]];
[sortedTitles addObject:[dict valueForKey:key]];
}
NSLog(#"%#",sortedValues);
sortedTitles should give you the array sorted in the same order as sortedFloats.
hey instead of taking two different array take 1 dictionary with key title,distance save that dictionary in array then sort that array So you have got combination together so there is no any problem due to mapping in any sort(by title & by distance).
if i understand your question right , you can use NSDictionary for the same task
NSMutableArray *array = [NSMutableArray arrayWithArray:#[ #{#"title" : #"City1",#"dist" : #5},
# {#"title" : #"City2",#"dist" : #2.3 },
#{#"title" : #"City3",#"dist" : #11.0 },
#{#"title" : #"City4",#"dist" : #1.0},
#{#"title" : #"City5",#"dist" : #.5},
#{#"title" : #"City6",#"dist" : #13 }]];
NSLog(#"dict<%#>",array);
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"dist" ascending:YES];
NSArray *sortarray = [array sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];
NSLog(#"sort array = <%#>",sortarray);
I got the solution see following code.........
NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"self" ascending:YES]autorelease];
sortedFloats = [appDel.Arr_distance sortedArrayUsingDescriptors:
[NSArray arrayWithObject:sortDescriptor]];
NSLog(#" Sorted Array : %#", sortedFloats);
NSDictionary *dictTitle = [NSDictionary dictionaryWithObjects:Arr_title forKeys:appDel.Arr_distance];
// Sort the second array based on the sorted first array
sortedTitle = [dictTitle objectsForKeys:sortedFloats notFoundMarker:[NSNull null]];
NSLog(#" Sorted Title : %#",sortedTitle);
// Put the two arrays into a dictionary as keys and values
NSDictionary *dictAddress = [NSDictionary dictionaryWithObjects:Arr_address forKeys:appDel.Arr_distance];
// Sort the second array based on the sorted first array
sortedAddress = [dictAddress objectsForKeys:sortedFloats notFoundMarker:[NSNull null]];
NSLog(#" Sorted Address : %#",sortedAddress);
Dont forgot to retain your arrays if use in another method ....

Sort array having object of class

Hi I have an array having 100 element. and each element is of type class Data with the following members:
name
price
stock
description
How can I sort the array on based on the price member of class Data?
NSSortDescriptor *priceDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"price" ascending:YES] autorelease]; // ascending YES or NO depends on your requirement
NSArray *sortDescriptors = [NSArray arrayWithObject: priceDescriptor];
NSArray *sortedArray = [yourArray sortedArrayUsingDescriptors:sortDescriptors];
also see this
if you have method for price the object within array class you can use NSComparisonResult:
- (NSComparisonResult) compareprice : (id) element
{
return [price compare: [element price ]];
}