Reputation: 1153
I have an NSArray
containing several NSDictionary
instances. Each NSDictionary
has, among other fields, an object named rating
and one numberOfVotes
(both are int
). How can I sort the array so it gets sorted by rating
/numberOfVotes
? More generically, can I sort it by doing an operation like mentioned above? Or would it be better to just add another object to each NSDictionary
with the value of each operation and then sort by that?
Thanks
EDIT - I have added the following. Still not sorting properly. One question: Should this work for more than 2 objects in my array. (The number of objects will vary)
[sortedArray sortedArrayUsingComparator:^NSComparisonResult(id dict1, id dict2)
{
MyObj *obj1 = (MyObj *)dict1;
MyObj *obj2 = (MyObj *)dict2;
int rating1 = obj1.rating.intValue;
int rating2 = obj2.rating.intValue;
int number1 = obj1.number_of_votes.intValue;
int number2 = obj2.number_of_votes.intValue;
double key1 = ((double)rating1)/number1;
double key2 = ((double)rating2)/number2;
if (key1 < key2)
{
return NSOrderedDescending;
}
if (key2 < key1)
{
return NSOrderedAscending;
}
return NSOrderedSame;
}];
Upvotes: 2
Views: 1045
Reputation: 726909
You can define a custom comparator to use a composite sorting key of the kind that you are looking for. If there is no good reason to have that sorting key in the dictionary, other than performing the sort, do not add an item to the dictionary.
array = [array sortedArrayUsingComparator: ^(id obj1, id obj2) {
int rating1 = [[obj1 objectForKey:@"rating"] intValue];
int numberOfVotes1 = [[obj1 objectForKey:@"numberOfVotes"] intValue];
int rating2 = [[obj2 objectForKey:@"rating"] intValue];
int numberOfVotes2 = [[obj2 objectForKey:@"numberOfVotes"] intValue];
double key1 = ((double)rating1)/numberOfVotes1;
double key2 = ((double)rating2)/numberOfVotes2;
if (key1 > key2) {
return (NSComparisonResult)NSOrderedDescending;
}
if (key1 < key2) {
return (NSComparisonResult)NSOrderedAscending;
}
return (NSComparisonResult)NSOrderedSame;
}];
Note: The sortedArrayUsingComparator:
method does not sort the array in place; instead, it returns a sorted copy. If you would like an in-place sorting, use NSMutableArray
.
Upvotes: 4
Reputation: 328
you can use NSSortDescriptor here for sorting for example your array that containing several NSDictionnaries name is dataArray.
NSSortDescriptor * descriptor = [[NSSortDescriptor alloc] initWithKey:rating
ascending:YES];
NSArray * keyArrray = [NSArray arrayWithObjects:descriptor, nil];
NSArray * sortedArray = [dataArray sortedArrayUsingDescriptors:keyArrray];
With the help of NSSortDescriptor we can sort any data type key value pair.
Upvotes: 0
Reputation: 130152
Ideally, you should substitute NSDictionary
by a custom object, with properties like rating
and numberOfVotes
. Then, you could declare a method compare:
on this custom object and use as the selector to sort the array.
You can use a block code to sort the objects but abstracting the implementation into a custom object is much cleaner.
Upvotes: 0
Reputation: 31311
Filtering data is one of the essential tasks in computing.
You can sort it several ways.
You can see examples here
You can see examples here
Regular Expressions
Set Operations
Key-Value Coding
Upvotes: 0
Reputation: 477
The adequate way would be using blocks like this
NSArray *sortedArray;
sortedArray = [unsortedArray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
float first = [[(NSDictionary*)a objectForKey:@"rating"] floatValue]/
[[(NSDictionary*)a objectForKey:@"numberOfVotes"] floatValue];
float second = [[(NSDictionary*)a objectForKey:@"rating"] floatValue]/
[[(NSDictionary*)a objectForKey:@"numberOfVotes"] floatValue];
return [[NSNumber numberWithFloat:first] compare: [NSNumber numberWithFloat:second]];
}];
you may find more ways to compare:
How to sort an NSMutableArray with custom objects in it?
Upvotes: 1
Reputation: 7615
Edit: If you want to do rating
divided by numberOfVotes
, you will have to sort by a function or comparator block or replace the dictionary with a model object which has a method to calculate rating / numberOfVotes
.
Use NSSortDescriptor
.
NSArray *sorted = [array sortedArrayUsingDescriptors:[NSArray arrayWithObjects:
[NSSortDescriptor sortDescriptorWithKey:@"rating" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:@"numberOfVotes" ascending:YES],
nil]
];
Upvotes: 0
Reputation: 104698
The family of methods you seek are prefixed with sortedArray
.
For a function (which is one of multiple options), see: -[NSArray sortedArrayUsingFunction:context:]
.
Upvotes: 0