I have a NSMutableArray containing NSStrings of various lengths. How would I go about sorting the array by the string length?
See my answer to sorting arrays with custom objects:
NSSortDescriptor *sortDesc= [[NSSortDescriptor alloc] initWithKey:#"length" ascending:YES];
[myArray sortUsingDescriptors:#[sortDesc]];
This is how I did it (love me some blocks!)
_objects = [matchingWords sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
NSNumber *alength = [NSNumber numberWithInt:((NSString*)a).length];
NSNumber *blength = [NSNumber numberWithInt:((NSString*)b).length];
return [alength compare:blength];
}];
Related
I have an nsmutable array of friends list.each having their lat&longs.I want to sort that array with the ascending rate of their distances from the autor.I found out the distances values of the friends with the autor,Now I want to sort that array in the ascending of their distances.This is how i am doing that,`
for(int i=0;i<[searchfriendarray count];i++)
{
NSDictionary *payload =[searchfriendarray objectAtIndex:i];
NSLog(#"%#",payload);
NSString *memberid = [payload objectForKey:#"userID"];
CLLocation *locationofauthor;
CLLocation *locationoffriends;
if([memberid isEqualToString:uidstr])
{
NSString *latofauthor = [payload objectForKey:#"latitude"];
NSString *longofauthor=[payload objectForKey:#"longitude"];
double latofauthordouble = [latofauthor doubleValue];
double longofauthordouble=[longofauthor doubleValue];;
locationofauthor = [[CLLocation alloc] initWithLatitude:latofauthordouble longitude:longofauthordouble];
}
else
{
NSString *latoffriends = [payload objectForKey:#"latitude"];
NSString *longoffriends=[payload objectForKey:#"longitude"];
double latoffriendsdouble = [latoffriends doubleValue];
double longoffriendsdouble=[longoffriends doubleValue];;
locationoffriends = [[CLLocation alloc] initWithLatitude:latoffriendsdouble longitude:longoffriendsdouble];
}
CLLocationDistance distance = [locationofauthor distanceFromLocation:locationoffriends];
}
`Can any body help me to sort my array in the ascecending order of the distances?
You can supply a block of comparison code between 2 objects. NSArray will then call your block as many times as it needs to sort the array.
NSArray sortedArray = [yourUnsortedArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
/*some code to compare obj1 to obj2.
for instance, compare the distances of obj1 to obj2.
Then return an NSComparisonResult
(NSOrderedAscending, NSOrderedSame, NSOrderedDescending);*/
}];
p.s. to get a mutable array again, just call mutableCopy on the returned object.
NSSortDescriptor * descLastname = [[NSSortDescriptor alloc] initWithKey:#"active" ascending:YES];
[livevideoparsingarray sortUsingDescriptors:[NSArray arrayWithObjects:descLastname, nil]];
[descLastname release];
videoparsing = [livevideoparsingarray copy];
livevideoparsingarray is my array which I have sort & active is my tag which is in array which I have sort. You change with your requirements.
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 ....
the problem im having is that i cant sort an NSMutableArray of NSMutableDictionary Objects, I want to sort the objects by rating, the rating is a NSNumber, what am i missing?
My current code that sums all the ratings from "arrayMealRating" and sorts the resulting array:
[arrayMealRating addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:
[eachObject objectForKey:#"Airline"], #"Airline"
,[eachObject objectForKey:#"setMealRating"], #"setMealRating"
, nil]];
}
NSArray *airlineNames = [arrayMealRating valueForKeyPath:#"#distinctUnionOfObjects.Airline"];
// Loop through all the airlines
for (NSString *airline in airlineNames) {
// Get an array of all the dictionaries for the current airline
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(Airline == %#)", airline];
NSArray *airlineMealRating = [arrayMealRating filteredArrayUsingPredicate:predicate];
// Get the sum of all the ratings using KVC #sum collection operator
NSNumber *rating = [airlineMealRating valueForKeyPath:#"#sum.setMealRating"];
//NSLog(#"%#: %#", airline, rating);
[sortedMealArray addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:
airline, #"Airline"
,[rating stringValue], #"setMealRating"
, nil]];
}
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"setMealRating" ascending:YES];
[sortedMealArray sortedArrayUsingDescriptors:[NSMutableArray arrayWithObjects:descriptor,nil]];
auxMealRating = [sortedMealArray copy];
Any doubt, please dont down vote, just ask and i will edit the question.
Best Regards and sorry for my poor english.
This should do what you want:
NSArray *sortedArray = [arrayMealRating sortedArrayUsingComparator:^(id obj1, id obj2) {
NSNumber *rating1 = [(NSDictionary *)obj1 objectForKey:#"setMealRating"];
NSNumber *rating2 = [(NSDictionary *)obj2 objectForKey:#"setMealRating"];
return [rating1 compare:rating2];
}];
I have two arrays, both full of NSString objects like this:
NSMutableArray *titles = [[NSMutableArray alloc] initWithObjects:#"Title1", #"Title2", #"Title3", #"Title4", #"Title5", nil];
NSMutableArray *distances = [[NSMutableArray alloc] initWithObjects:#"139.45", #"23.78", #"347.82", #"10.29", #"8.29", nil];
How can I sort both arrays by the nearest distance first?
So the results would be like this:
titles = #"Title5", #"Title4", #"Title2", #"Title1", #"Title3"
distances = #"8.29", #"10.29", #"23.78", #"139.45", #"347.82"
I understand that NSSortDescriptor can be used in these circumstances but after looking through the documentation, I am still unsure about how.
I would sort the distances this way...
NSNumberFormatter *f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSArray *sortedDistances = [listItem sortedArrayUsingComparator: ^(id a, id b) {
NSNumber *aNum = [f numberFromString:a];
NSNumber *bNum = [f numberFromString:b];
return [aNum compare:bNum];
}];
I can't think of a particularly quick way to get the associated titles sorted, but this should work ...
NSMutableArray *sortedTitles = [NSMutableArray array];
NSDictionary *distanceTitle = [NSDictionary dictionaryWithObjects:titles forKeys:distances];
for (NSString *distance in sortedDistances) {
NSString *associatedTitle = [distanceTitle valueForKey:distance];
[sortedTitles addObject:associatedTitle];
}
You can use an NSComparator block and use NSArray's sortedArrayUsingComparator method. On that block, you will receive two objects to compare, and base on the comparison result, you can use NSMutableArray exchangeObjectAtIndex:withObjectAtIndex: method to change the values of titles.
Here is a sample how I sort an array of dictionaries by distance value:
-(void)reorderByDistance {
NSSortDescriptor *sortByName = [NSSortDescriptor sortDescriptorWithKey:#"distance" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortByName];
self.contentArray = [self.contentArray sortedArrayUsingDescriptors:sortDescriptors];
}
And my dictionary looks like this:
NSDictionary *dict1 = [[NSDictionary alloc] initWithObjectsAndKeys:#"1", #"id", #"Business #1", #"name", #"This business does some pretty remarkable things", #"description", #"Alley Bar", #"category", #"1.2", #"distance", nil];
One approach would be to create a dictionary mapping titles to distances, sort the distances, and then iterate through the distances to recreate the titles:
NSMutableArray *titles = [[NSMutableArray alloc] initWithObjects:#"Title1", #"Title2", #"Title3", #"Title4", #"Title5", nil];
NSMutableArray *distances = [[NSMutableArray alloc] initWithObjects:#"139.45", #"23.78", #"347.82", #"10.29", #"8.29", nil];
//Create a map of current titles to distances
NSDictionary *titleDistanceMap = [NSDictionary dictionaryWithObjects:titles forKeys:distances];
//Need to sort the strings as numerical values
[distances sortUsingComparator:^(NSString *obj1, NSString *obj2) {
return [obj1 compare:obj2 options:NSNumericSearch];
}];
//Now re-populate the titles array
[titles removeAllObjects];
for (NSString *distance in distances){
[titles addObject:[titleDistanceMap objectForKey:distance]];
}
So I have the kind of classic situation where I want to group my tableView by Month/Year. I have a member of my conference object called beginDateSearchString that I use to put different conference into buckets; my problem is in the next part where I try and fail to use a NSSortDescriptor to sort each bucket by beginDate (which is a date).
I am getting an error related to unsorted not being able to receive sort descriptor type selectors.
Here is the disgusting code:
- (NSArray *)arrayOfDateSortedEvents {
NSMutableArray *sortedArray = [[NSMutableArray alloc] init];
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
//place into buckets
for (WSConference *conference in self.arrayOfEvents) {
if (![dictionary objectForKey:[conference beginDateSearchString]]) {
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:conference,nil];
[dictionary setObject:array forKey:[conference beginDateSearchString]];
}
else {
[[dictionary objectForKey:[conference beginDateSearchString]] addObject:conference];
}
}
//sort each bucket by descriptor beginDate
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"beginDate" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:descriptor];
for (NSMutableArray *unsorted in dictionary) {
[unsorted sortUsingDescriptors:sortDescriptors];
}
// now, unkey and add dictionary in order
while ([dictionary count] > 0) {
NSString *lowest = nil;
for (NSMutableArray *array in dictionary) {
if (!lowest)
lowest = [[dictionary allKeysForObject:array] objectAtIndex:0];
else {
if ([(WSConference *)[array objectAtIndex:0] beginDate] < [[dictionary objectForKey:lowest] beginDate])
lowest = [[dictionary allKeysForObject:array] objectAtIndex:0];
}
}
[sortedArray addObject:[dictionary objectForKey:lowest]];
[dictionary removeObjectForKey:lowest];
}
return sortedArray;
}
You want to probably filter the array in addition to sorting. See NSPredicate and the NSArray method -filteredArrayUsingPredicate: Then create an eventsByDateArray of the eventArrays created by the filter. Then in your table view delegate for creating the cells, if everything is ordered properly, the first section would represent the date of the events in the eventArray that is the first object of the eventsByDateArray and the table rows would consist of the events in the eventArray. And so on for each date.
Added
Your fast enumeration is incorrect. You enumerate through the keys of the dictionary. So in your code unsorted equals each of the keys as it enumerates. This is a GREAT lesson to everyone. It does not matter how you 'type' a variable. When Objective-C compiles it turns them all into id. So NSMutableArray *unsorted is not an NSMutableArray unless it is assigned to an NSMutableArray. If you assign unsorted to an NSString it will be an NSString. The fast enumerator for a dictionary works using the keys. So, in this case, unsorted becomes an NSString.
Instead of:
for (NSMutableArray *unsorted in dictionary) {
[unsorted sortUsingDescriptors:sortDescriptors];
}
you should have this:
for (id key in dictionary) {
NSMutableArray *unsorted = [dictionary objectForKey:key];
[unsorted sortUsingDescriptors:sortDescriptors];
}