I've an array of objects, the size of which I cannot predict. The contents of the array are model objects with properties of type nsstring and nsnumber.
I need to sort the array according to one of the properties, an nsnumber. How would you do it in objective-c/Cocoa? Implement quicksort or some other algorithm (which one)? Any libraries that handle that for you?
Update
While the response below is correct, it only works on 10.6 and I'm targeting 10.5.
NSArray has several sorting methods. Given your array, arr,
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"numberProperty" ascending:YES];
NSArray *sortedArr = [arr sortedArrayUsingSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
will give you an array sorted (ascending) by #"numberProperty". Obviously, you'll have to substitute the name of the NSNumber property in your model objects for #"numberProperty".
The sorting algorithm is not specified in NSArray's sorting methods.
This is what I came up with:
NSArray *unsortedArray = [results allValues];
NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc]
initWithKey:#"ordinalPosition"
ascending:YES]
autorelease];
NSArray *sortedArray = [unsortedArray
sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
Use qsort() from stdlib.h.
Related
Trying to sort an array of dictionaries. There are two arrays in the plist file and I am trying to sort one of them and having a lot of trouble. I can extract the dictionaries into a NSArray and sort the files.
I can only do this by extracting the dictionaries so when I try to save the information back to the plist I've lost my structure and other array of dictionaries.
How can I sort the array correctly. I understand I'm extracting the array and then saving it as it's own file. I see what I'm doing wrong but can't figure how the correct way.
NSArray *array = [dict valueForKey:#"Lighting"];
NSSortDescriptor* nameSortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"Controller Zone" ascending:YES];
NSArray* sortedArray = [array sortedArrayUsingDescriptors:[NSArray arrayWithObject:nameSortDescriptor]];
NSString *pathToFileExportSorted = #"/Users/scott/Desktop/plistPreSEsorted.plist";
[sortedArray writeToFile:pathToFileExportSorted atomically: YES];
I have tried something like this but couldn't get that working either
[array sortUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"Lighting.Controller Zone" ascending:YES]]];
I just want to sort the Array Lighting by "Controller Zone" and keep the plist as is otherwise.
Thanks for any help.
Original Data:
What I am currently Exporting, does not have Lighting and Shade array. The array is now the only thing in the plist.
it's needed to assign sorted array to Lighting key
...and to save your initial dictionary with changed Lighting key
NSArray *array = [dict valueForKey:#"Lighting"];
NSSortDescriptor *nameSortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"Controller Zone" ascending:YES];
NSArray *sortedArray = [array sortedArrayUsingDescriptors:[NSArray arrayWithObject:nameSortDescriptor]];
NSMutableDictionary *dictToSave = [[dict mutableCopy] autorelease];
[dictToSave setObject:sortedArray forKey:#"Lighting"];
NSString *pathToFileExportSorted = #"/Users/scott/Desktop/plistPreSEsorted.plist";
[dictToSave writeToFile:pathToFileExportSorted atomically:YES];
That should work as you've described.
I have a problem with sorting... I need to sort NSArray containing NSDictionaries. As an order key I have to use element from the NSDictionary.
I was reading a little about sorting NSArray but it is not clear to me.
Could you try help me?
Use an NSSortDescriptor and a keypath. Assuming the key for the dictionary is key:
NSSortDescriptor *sd = [NSSortDescriptor sortDescriptorWithKey:#"key" ascending:YES];
NSArray *sorted = [array sortedArrayUsingDescriptors:[NSArray arrayWithObject:sd]];
I am attempting to sort an NSArray that is populated with custom objects. Each object has a property startDateTime that is of type NSDate.
The following code results in an array, sortedEventArray, populated but not sorted. Am I going about this the completely wrong way or am I just missing something small?
NSSortDescriptor *dateDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"startDateTime"
ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:dateDescriptor];
NSArray *sortedEventArray = [nodeEventArray sortedArrayUsingDescriptors:sortDescriptors];
Are you sure that the startDateTime instance variables of the node events are non-nil?
If you don't have one already, you might add a (custom) -description method to your node event objects that does something like this:
- (NSString *)description {
return [NSString stringWithFormat:#"%# - %#",
[super description], startDateTime]];
}
Then in your sorting code log the array before and after:
NSLog(#"nodeEventArray == %#", nodeEventArray);
NSSortDescriptor *dateDescriptor = [NSSortDescriptor
sortDescriptorWithKey:#"startDateTime"
ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:dateDescriptor];
NSArray *sortedEventArray = [nodeEventArray
sortedArrayUsingDescriptors:sortDescriptors];
NSLog(#"sortedEventArray == %#", sortedEventArray);
If the startDateTime's are all nil, then the before and after arrays will have the same order (since the sorting operation will equate to sending all the -compare: messages to nil, which basically does nothing).
Did you try by specifying the NSDate comparator?
Eg:
NSSortDescriptor *dateDescriptor = [NSSortDescriptor
sortDescriptorWithKey:#"startDateTime"
ascending:YES
selector:#selector(compare:)];
This should enforce the usage of the correct comparator of the NSDate class.
Ok, I know this is a little late, but this is how I would do it:
NSArray *sortedEventArray = [events sortedArrayUsingComparator:^NSComparisonResult(Event *event1, Event *event2) {
return [event1.startDateTime compare:event2.startDateTime];
}];
Obviously, replace Event with the class of your custom object. The advantage of this approach is that you are protected against future refactoring. If you were to refactor and rename the startDateTime property to something else, Xcode probably would not change the string you're passing into the sort descriptor. Suddenly, your sorting code would break/do nothing.
You can achieve like this,
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"anyDateField" ascending:YES];
NSMutableArray *arr = [[array sortedArrayUsingDescriptors:[NSArray arrayWithObjects:descriptor,nil]]mutableCopy];
You can achieve this like this,
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"date" ascending:FALSE];
[self.Array sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
I have an array which contains dictionaries in it; so how can I sort the array according to dictionary key values?
If every element in the array is a dictionary containing a certain key, you can sort the array using a sort descriptor. For instance, if every element is a dictionary containing a key called "name":
NSSortDescriptor *sortByName = [NSSortDescriptor sortDescriptorWithKey:#"name"
ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortByName];
NSArray *sortedArray = [array sortedArrayUsingDescriptors:sortDescriptors];
The other way to achieve this would be using sortedArrayUsingComparator: method
NSArray *sortedArray = [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [[obj1 valueForKey:#"value"] compare:[obj2 valueForKey:#"value"]];
}];
why don't you use a sorted dictionary where the property of sorted elements comes already with the data structure?
Please do check it out here
Hope this helps.
The above shared answer by Bavarious helped me.Just want to add one more thing.If you want to sort a mutable array use something like the below code
NSSortDescriptor *sortByName = [NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortByName];
NSMutableArray *sortedArray = [[NSMutableArray sortedArrayUsingDescriptors:sortDescriptors]mutableCopy];
let arrDescriptor = NSSortDescriptor(key: "order", ascending: true)
let sortDescriptors: NSArray = [arrDescriptor]
let sortedArray = instancesubArray.sortedArray(using: sortDescriptors as [AnyObject] as [AnyObject] as! [NSSortDescriptor])
print(sortedArray)
I have an array of custom objects. One of the properties of these objects is an NSString. I want to sort by that property.
Because it is an NSString and not an NSNumber sorting is a little more difficult. Is there some kind of class method to help in this case? How should it be done?
There is indeed. NSArray has a -sortedArrayUsingDescriptors: method. Call this, and pass an array of one sort descriptor for your property. For example, if your property is "lastName", then:
NSSortDescriptor *desc = [[[NSSortDescriptor alloc] initWithKey: #"lastName" ascending: YES];
[array sortedArrayUsingDescriptors: [NSArray arrayWithObject: desc]];