Sorting an NSArray of NSDictionary - iphone

I have to sort an array of dictionaries but I have to order by an object in the dictionaries.

Use NSSortDescriptors with -sortedArrayUsingDescriptors:. For the key path, pass in the dictionary key, followed by the object's key(s) by which you want to sort. In the following example, you have an array of dictionaries and those dictionaries have a person under "personDictionaryKey", and the "person" has a "lastName" key.
NSSortDescriptor * descriptor = [[[NSSortDescriptor alloc] initWithKey:#"personInDictionary.lastName"
ascending:YES] autorelease]; // 1
NSArray * sortedArray = [unsortedArray sortedArrayUsingDescriptors:
[NSArray arrayWithObject:descriptor]];
1 - In 10.6 there are class convenience methods for creating sort descriptors but as bbum's answer says, there are now blocks-enabled sorting methods and I'm betting they're a lot faster. Also, I noticed your question is for iOS, so that's probably irrelevant. :-)

To rephrase; you want to sort the array by comparing dictionary contents? (I.e. you know you can't sort a dictionary's contents, right?)
As Joshua suggested, use NSSortDescriptor and sortedArrayUsingDescriptors:. This is quite likely the best solution; at least the most straightforward.
There are other ways, too.
Assuming you are targeting iOS 4.0, then you can use sortedArrayUsingComparator: and pass a block that'll do the comparison of the two dictionary's contents.
If you are targeting iOS 3.x (including the iPad), then you would use sortedArrayUsingFunction:context:.
Or, as Joshua suggested, use NSSortDescriptor and sortedArrayUsingDescriptors:
All are quite well documented, with examples.

here is an implementation with custom objects instead of dictionaries:
ArtistVO *artist1 = [ArtistVO alloc];
artist1.name = #"Trentemoeller";
artist1.imgPath = #"imgPath";
ArtistVO *artist2 = [ArtistVO alloc];
artist2.name = #"ATrentemoeller";
artist2.imgPath = #"imgPath2";
ArtistVO *artist3 = [ArtistVO alloc];
artist3.name = #"APhextwin";
artist3.imgPath = #"imgPath2";
//NSLog(#"%#", artist1.name);
NSMutableArray *arr = [NSMutableArray array];
[arr addObject:artist1];
[arr addObject:artist2];
[arr addObject:artist3];
NSSortDescriptor *lastDescriptor =
[[[NSSortDescriptor alloc]
initWithKey:#"name"
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)] autorelease];
NSArray * descriptors =
[NSArray arrayWithObjects:lastDescriptor, nil];
NSArray * sortedArray =
[arr sortedArrayUsingDescriptors:descriptors];
NSLog(#"\nSorted ...");
NSEnumerator *enumerator;
enumerator = [sortedArray objectEnumerator];
ArtistVO *tmpARt;
while ((tmpARt = [enumerator nextObject])) NSLog(#"%#", tmpARt.name);

Related

How to sort an NSArray full of EKCalendars by the title

I've got a NSArray with a bunch of EKCalendar Objects in it. I need to sort them alphabetically. I'm new to selectors but I think I need something like...
NSArray *array = [otherArray sortedArrayUsingSelector:#selector('localizedCaseInsensitiveCompare:title')];
Cheers
You cannot do it that way. Instead do the following:
NSArray *sortedArray = [array sortedArrayUsingComparator: ^(id obj1, id obj2) {
EKCalendar *cal1 = (EKCalendar *)obj1;
EKCalendar *cal2 = (EKCalendar *)obj2;
return [cal1.title localizedCaseInsensitiveCompare:cal2.title];
}];
Edit - an explanation:
-sortedArrayUsingComparator takes what is called a 'block' (an inline function) that must return an NSComparisonResult. All the hard work is done for you, as your block is run for as many pairs of objects as is needed to establish the correct order. Then all this does is cast each object type to an EKCalendar and then compare the two titles. You can adapt this to work for any type of object.
This should do the trick:
NSMutableArray *sortDescriptors = [NSMutableArray array];
NSSortDescriptor *sortByTitleAsc = [[[NSSortDescriptor alloc] initWithKey:#"title" ascending:YES] autorelease];
[sortDescriptors addObject:sortByTitleAsc];
NSArray *arraySortedByTitle = [otherArray sortedArrayUsingDescriptors:sortDescriptors];
No, you don't want to use a selector, you want to use a key path, which requires a sort descriptor. You can't append an arbitrary property name to a selector name. The selector must exactly match the method name. Otherwise you just get nothing (nil/NULL/0) for the selector.
id sortedArray = [array sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"title" ascending:YES]]];
For the sake of completeness and and timeliness, here’s the Swift 4 version:
let store = EKEventStore()
let calendars = store.calendars(for: .event)
let calendarsSorted = calendars.sorted { $0.title.localizedCaseInsensitiveCompare($1.title) == ComparisonResult.orderedAscending }
By the way, please don’t forget to request access to the store by calling store.requestAccess(to:completion:) before accessing the store’s data.

Objective-c: how to sort a NSMutableArray of UIButtons using their tags

I have a NSMutableArray containing UIButtons. I have given each of the buttons a unique
tag. The buttons will be added to the array in random order, but i want to later sort it so that the buttons are in ascending order with respect to their tags.
Thanks for the help!
Yeap.
Try this:
NSSortDescriptor *ascendingSort = [[NSSortDescriptor alloc] initWithKey:#"tag" ascending:YES];
NSSortDescriptor *descendingSort = [[NSSortDescriptor alloc] initWithKey:#"tag" ascending:NO];
NSArray *sortedArray = [someArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:ascendingSort]];
You can use the NSSortDescriptor to sort a NSArray.
NSArray *unsortedArray = ...
NSArray *sortedArray = [unsortedArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"tag" ascending:YES]]];
There are multiple "sortedArrayUsing..." functions. Use the one that seems to fit your needs the best.
(BTW, remember that, since NSMutableArray is a subclass of NSArray, all of the methods of NSArray apply to NSMutableArray as well.)

Sorting Array of Custom Class Objects

I am facing problem that is of sorting. The scenario is explained as: i have a class (Suppose of person) and it has suppose 4 attributes (firstName, lastName, Address, salary) i am creating its object and making a collection of all attributes and putting this object in a NSMutableArray and so on. So at every index of array i have one object (i.e collection of 4 attributes). Now i want to sort that array on the basis of salary can anyone help me out regarding this problem, will be thankful.,
See the documentation for NSArray. It has several sorting methods. Search for the word "sort" and you'll find 'em. (You'll want either the block based or function based API).
use this
NSSortDescriptor *sorter = [[[NSSortDescriptor alloc] initWithKey:#"salary" ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject: sorter];
[yorArrary sortUsingDescriptors:sortDescriptors];
Either you implement a compare-method for your object:
- (NSComparisonResult)compare:(Person *)otherObject {
return [self.birthDate compare:otherObject.birthDate];
}
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingSelector:#selector(compare:)];
or usually even better: (The default sorting selector of NSSortDescriptor is compare:)
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"birthDate"
ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptors:sortDescriptors];

Sort UITableView in Russian alphabetical order

I'm a noob, and I'm sorry because the question is really stupid. I have An NSArray which contains titles for UITableView rows in NSDictionaries in Russian and I need to sort these titles in alphabetical order. How can I do it?
Help me, please.
Thanks in advance!
On iOS 4.0 and later, you can use a sort descriptor. Assuming title is the key under which your title strings are stored in the dictionaries:
NSArray *sortedArray = [myArray sortedArrayUsingDescriptors:
[NSArray arrayWithObject:
[NSSortDescriptor sortDescriptorWithKey:#"title"
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)]]];
Another option is to use a block-based sort method:
NSArray *sortedArray = [myArray sortedArrayUsingComparator:^(id obj1, id obj2) {
NSString *string1 = [(NSDictionary *)obj1 objectForKey:#"title"];
NSString *string2 = [(NSDictionary *)obj2 objectForKey:#"title"];
return [string1 localizedCaseInsensitiveCompare:string2];
}];
If you need your app to run on iOS 3.1.3 and earlier, however, you can either:
write a comparison method as a category on NSDictionary and pass it to -sortedArrayUsingSelector:, or
write a comparison function and pass it to -sortedArrayUsingFunction:context:.
In each case, your method or function's body will be essentially the same as the body of the block in the second example above. The NSArray class reference contains examples of both techniques.
I think this will sort your array:
NSArray *sortedArray = [anArray sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];

Sorting an Array of custom objects by a dictionary included in the custom object: How?

I have an array of custom objects. The objects includes a dictionary.
Something like this:
CustomDataModel *dataModel;
dataModel.NSString
dataModel.NSDictionary
dataModel.image
I'd like to sort by one of the objects in the dictionary:
dataModel.NSDictionary ObjectWithkey=#"Name"
The dataModel gets loaded into an NSArray. I now want to sort the by the #"Name" key in the dictionary. Is this something NSSortDescriptor can handle? Basic sort works fine, just haven't figured this one out yet...
Your question isn't completely clear to me, but you can try something like this on your NSArray:
- (NSArray *)sortedItems:(NSArray*)items;
{
NSSortDescriptor *sortNameDescriptor =
[[[NSSortDescriptor alloc]
initWithKey:#"Name" ascending:NO]
autorelease];
NSArray *sortDescriptors =
[[[NSArray alloc]
initWithObjects:sortNameDescriptor, nil]
autorelease];
return [items sortedArrayUsingDescriptors:sortDescriptors];
}
//Sort an array which holds different dictionries - STRING BASED - Declare it in the .h
- (NSArray *)sortStringsBasedOnTheGivenField:(id)dictionaryKey arrayToSort:(NSMutableArray *)arrayToHoldTemp ascending:(BOOL)ascending {
NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:dictionaryKey ascending:ascending selector:#selector(localizedCaseInsensitiveCompare:)] ;
NSArray *descriptors = [NSArray arrayWithObject:nameDescriptor];
[arrayToHoldTemp sortUsingDescriptors:descriptors];
[nameDescriptor release];
return arrayToHoldTemp;
}
Usage:
self.mainArrayForData = [NSArray arrayWithArray:[self sortNumbersBasedOnTheGivenField:#"Name" arrayToSort:arrayWhichContainsYourDictionries ascending:YES]];
the above method is good for an array that holds dictionaries