sort NSDictionary based on single object key - ios

I would like some help sorting an NSArray of NSDictionary values based on each objects ISV key.
This is the code I have so far for creating my array objects so you have a better idea of what I am trying to do.
NSArray *combinedKeysArray = [NSArray arrayWithObjects:#"HASM", #"ISL", #"ISV", nil];
valuesCombinedMutableArray = [NSMutableArray arrayWithObjects:[dict objectForKey:#"HASM"],
[dict objectForKey:#"ISL"],
[dict objectForKey:#"ISV"],
nil];
combinedDictionary = [NSDictionary dictionaryWithObjects:valuesCombinedMutableArray
forKeys:combinedKeysArray];
[unSortedrray addObject:combinedDictionary];
// how do I then sort unSortedArray by the string values in each object ISV key?
any help would be greatly appreciated.

This can solve your problem
How to sort an NSMutableArray with custom objects in it?
https://stackoverflow.com/a/805589/1294448
You can use NSSortDescriptor to sort NSArays
Then in NSArray you have a method called sortedArrayUsingDescriptors
Or NSComparisonResult ca also be helpful some time http://developer.apple.com/DOCUMENTATION/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html#//apple_ref/doc/uid/20000138-BABCEEJD

you won't be able to sort unSortedArray because it will only have one element in it (ie in your last line of code you are adding a single object by addObject).
That said, you cannot sort the dictionary either.. b/c dictionaries are unsorted by definition.
you can iterate over the keys of the dictionary in a specific order though, you can sort an array containing the keys of the dictionary.
NSArray *keys = [theDictionary allKeys];
NSArray *sortedKeys = [keys sortedArrayUsingSelector:#selector(compareMethod:)];

You can use -sortedArrayUsingComparator: to sort any way you need.
[unSortedrray sortedArrayUsingComparator:^NSComparisonResult(NSDictionary *dict1, NSDictionary *dict2) {
return [[dict1 objectForKey:#"ISV"] localizedCompare:[dict2 objectForKey:#"ISV"]];
}];

Related

Objective-c NSDictionary to NSMutableArray in certain order

So I have this NSDictionary like so:
NSDictionary *productionSchedule = [[[NSMutableDictionary alloc]initWithDictionary:[[areaData GetProductionScheduleData:communityDesc] objectForKey:#"Root"]] autorelease];
The data for the NSDictionary is coming from an API and due to the fact that NSDictionary does not do ordering, the order of the data in API is different in the NSDictionary, so now I am trying to put the keys of the NSDictionary into an NSMutableArray to handle the ordering. In my NSDictionary I have a value called SortOrder and I am trying to put the data in NSDictionary into NSMutableArray based on this value SortOrder (I have about 389 items and the SortOrder goes from 0 - 389) How would I do this?
I have this screenshot that will show you what my data is like:
What I am trying to do is put the key 'V3C0183' but as the 82nd item (there will be 81 items before this)
I am assuming I will have to do a foreach loop like so:
NSMutableArray *prodSchedSortedKeys
for(int i = 0;i<[productionSchedule count];i++)
{
[prodSchedSortedKeys addObject: ? ];
}
I just dont know what the next step would be to add an object based off the sort order....please help.
NSDictionary *dic = //your dictionary;
NSArray<NSDictionary *> *values = dic.allValues;
[values sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
return [obj1[#"SortOrder"] integerValue] > [obj2[#"SortOrder"] integerValue];
}];
Now the dic is ordered.
But this is not the best solution of this problem. Server's data should be ordered instead, that the key like "VC31083" should in the key-value pairs too.
Edit1: sortedArrayUsingComparator: is used for normal sort of array, the performance isn't very well if the content is too large. Especially in this compare, it do addition actions: get value from dictionary, transform NSString to int, and then compare. You can Log to see how much time it spend on this sort with your data.
NSMutableDictionary/NSDictionary can't do that. Take a look at e.g. Matt Gallaghers OrderedDictionary.
Also take a look at this answer:
Getting NSDictionary keys sorted by their respective values

NSMutableDictionary key value shuffled

I am facing very strange problem in NSMutableDictionary. Please see the below code.
NSMutableDictionary *dict=[[NSMutableDictionary alloc]init];
[dict setValue:#"India" forKey:(#"Title")];
[dict setValue:#"Done" forKey:(#"Status")];
When I had printed this dictionary object, It shows like below.
{
Status =Done,
Title=India;
}
This keys getting shuffled, actually Title key should come first.
So, How can I resolve this issue.
That's not an issue.
You have mis understood or you'r getting wrong the NSDictionary. NSDictionary is a container to store values base on the keys.
So, there is no need of any order or indexing.
Reason behind is that you can only access container value if you know the key. So it is meaning less to check order of that keys. Because any how you have to use that key to access related value.
Now about order - Use NSArray instead and more of that use NSArray with object of NSDictionary. So that you have order with dictionary support.
Still the way to sort dictionary keys is below:
NSMutableDictionary *dict=[[NSMutableDictionary alloc]init];
[dict setValue:#"India" forKey:(#"Title")];
[dict setValue:#"Done" forKey:(#"Status")];
NSArray *keys = [dict allKeys];
keys = [keys sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSLog(#"%#",keys);
NSDictionary or NSMutableDictionary does not guarantee any ordering of it's key/value pairs. There's no way to keep your keys/values in a set order and it doesn't make sense for NSDictionary or NSMutableDictionary to work like this. (You use keys not indexes to retrieve values).
If you want your values or keys in a certain order for display purposes you can sort them after retrieving them:
NSArray * sortedKeys = [ [ myDictionary allKeys ] sortedArrayUsingSelector:... ] ;
or
NSArray * sortedKeys = [ [ myDictionary allKeys ] sortedArrayUsingComparator:... ] ;
You could then retrieve the associated objects for the sorted keys if you wanted.
Another option is to maintain 2 separate arrays, one for keys and one for values and keep them in order.

With fast enumeration and an NSDictionary, iterating in the order of the keys is not guaranteed – how can I make it so it IS in order?

I'm communicating with an API that sends back an NSDictionary as a response with data my app needs (the data is basically a feed). This data is sorted by newest to oldest, with the newest items at the front of the NSDictionary.
When I fast enumerate through them with for (NSString *key in articles) { ... } the order is seemingly random, and thus the order I operate on them isn't in order from newest to oldest, like I want it to be, but completely random instead.
I've read up, and when using fast enumeration with NSDictionary it is not guaranteed to iterate in order through the array.
However, I need it to. How do I make it iterate through the NSDictionary in the order that NSDictionary is in?
One way could be to get all keys in a mutable array:
NSMutableArray *allKeys = [[dictionary allKeys] mutableCopy];
And then sort the array to your needs:
[allKeys sortUsingComparator: ....,]; //or another sorting method
You can then iterate over the array (using fast enumeration here keeps the order, I think), and get the dictionary values for the current key:
for (NSString *key in allKeys) {
id object = [dictionary objectForKey: key];
//do your thing with the object
}
Dictionaries are, by definition, unordered. If you want to apply an order to the keys, you need to sort the keys.
NSArray *keys = [articles allKeys];
NSArray *sortedKeys = [keys sortedArrayUsingSelector:#selector(compare:)];
for (NSString *key in sortedKeys) {
// process key
}
Update the way the keys are sorted to suit your needs.
As other people said, you cannot garantee order in NSDictionary. And sometimes ordering the allKeys property it's not what you really want. If what you really want is enumerate your dict by the order your keys were inserted in your dict, you can create a new NSMutableArray property/variable to store your keys, so they will preserve its order.
Everytime you will insert a new key in the dict, insert it to in your array:
[articles addObject:someArticle forKey:#"article1"];
[self.keys addObject:#"article1"];
To enumerate them in order, just do:
for (NSString *key in self.keys) {
id object = articles[key];
}

Sorting the Key/Values stored in NSArray

I have a
NSDictionary* dict = [[NSDictionary alloc]initWithObjectsAndKeys::arrayOne,#"Plants",arrayTwo,#"Animals"),arrayThree,#"Birds",nil];`
self.displayArray =[[dict allKeys] sortedArrayUsingSelector:#selector(compare:)];
Everything works fine, I am able to see all the key value/pair in the table but they are in sorted order. i.e Animals,Birds,Plants.
But I want to display as Plants,Animals,Birds.
Can anyone tell me how to sort the array in my customized order?
I have googled and found that we can use NSSortDescriptor for sorting. But I am not very clear with that. Can anyone help me ?
As your ordering doesnt follow any natural order, a simple solution could be to keep track of the order with another array
NSArray *array1 = [NSArray arrayWithObjects:#"rose",#"orchid",#"sunflower",nil];
NSArray *array2 = [NSArray arrayWithObjects:#"dog", #"cat",#"ogre",#"wookie", nil];
NSArray *array3 = [NSArray arrayWithObjects:#"parrot",#"canary bird",#"tweety",#"bibo",nil];
NSArray *keys = [NSArray arrayWithObjects:#"Plants",#"Animals",#"Birds", nil];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
array1,[keys objectAtIndex:0],
array2,[keys objectAtIndex:1],
array3,[keys objectAtIndex:2],
nil];
for (NSString *key in keys) {
NSLog(#"%# %#", key, [dict objectForKey:key]);
}
Matt shows in his fantastic blog, how to create a ordered dictionary, that essentially uses another array to keep the order just as I showed here: OrderedDictionary: Subclassing a Cocoa class cluster
You're on the right track, Cyril.
Here is some Apple documentation on "Creating and using Sort Descriptors"
Basically you need to subclass NSSortDescriptor and in your subclass, implement your own "compare:" method (you can actually name it anything you want; it needs to return a "NSComparisonResult") that somehow logically returns "Plants" before "Animals".

how to remove object from NSDictionary

Hi i am having a NSdictionary in which i am adding a array with key "countries ". Now i take the value of this dictionary into array and sort the array in alpahbatical order .Now i want to add this array into my Dictionary (that is i want to update my dictionary with new sorted array and remove the old array from it )........ how to do this
My code is as follows
NSArray *countriesToLiveInArray = [NSArray arrayWithObjects:#"Iceland", #"Greenland", #"Switzerland", #"Norway", #"New Zealand", #"Greece", #"Italy", #"Ireland", nil];
NSDictionary *countriesToLiveInDict = [NSDictionary dictionaryWithObject:countriesToLiveInArray forKey:#"Countries"];
NSArray *tmpary = [countriesToLiveInDict valueForKey:#"Countries"];
NSLog(#"ary value is %#",ary);
NSArray *sortedArray = [tmpary sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
NSLog(#"sortedArray is %#",sortedArray);
Here i want to remove the countriesToLiveInArray and replace it with sortedArray with same key value i.e. Countries
Thanks in advance..
First you need to use a NSMutableDictionary and put this code :
[countriesToLiveInDict removeObjectForKey:#"Countries"];
[countriesToLiveInDict setObject:sortedArray forKey:#"Countries"];
First of all make your NSDictionary to NSMutableDictionary & then write the following line of code
[countriesToLiveInDict removeObjectForKey:#"Countries"];
This will definitely resolve your issue.
NSDictionary cannot remove anything, please use NSMutableDictionary, like this:
NSMutableDictionary *countriesToLiveInDict = [NSMutableDictionary dictionaryWithObject:countriesToLiveInArray forKey:#"Countries"];
for Swift 3
as #MathieuF answered it
First you need to use a NSMutableDictionary and put this code :
countriesToLiveInDict.removeObject(forKey: "Countries")
i post my answer as i was search for same question and get inspired by #MathieuF

Resources