Unable to sort NSMutableDictionary [Objective C] - objective-c

I populate an NSMutableDictionary with some Json, the problem is that even if the Json is ordered correctly the NSMutableDictionary reorder the values randomly (at least I don't know what's the logic behind it).
I tried to reorder the NSMutableDictionary using the following method but I still get the same result as the Json:
NSArray* sortedKeys = [theData allKeys];
NSMutableArray* orderHelper = [[NSMutableArray alloc] initWithArray:sortedKeys];
[orderHelper sortUsingComparator:^NSComparisonResult(NSString *str1, NSString *str2) {
return [str1 compare:str2 options:(NSNumericSearch)];
}];
NSMutableDictionary *sortedDictionary = [[NSMutableDictionary alloc] init];
for (NSString *key in orderHelper){
[sortedDictionary setObject:theData[key] forKey:key];
}
where theData is the first NSMutableDictionary containing the Json.
debugging I can see that the NSMutableArray gets ordered correctly but then on the for the NSMutableArray randomly reorders the items.
Does anyone have a solution for this?

Dictionaries (or Maps) are generally not an ordered data structure, and this is also the case for NSDictionary and the like. That means that the iteration order of your dictionary or the order of the allKeys array does not correspond to the insertion order of the associations you put into the dictionary.
So since the order is important to you, you have two options:
1) Use an OrderedDictionary implementation which does exactly that (preserve insertion order). There is none in the Objective-C standard library, but open-source alternatives are available.
2) Keep track of the order yourself in a separate NSArray in which you put the keys of your dictionary. Then, instead of iterating over your dictionary directly, you iterate over this array and read the corresponding values from the dictionary.
The internal order of a dictionary is entirely implementation-specific and of no value to you, since it might even be subject to changes. But very easily put, you can think about it the following way: The dictionary will assign a numerical value to each of your keys (e.g. foo is mapped to 0 and bar to 1. When you insert this key, it will add the value to a bucket at the corresponding numerical index. So regardless of the insertion order, foo will always end up in the first bucket, and bar will always end up in the second bucket. This is the order you can observe when subsequently iterating the dictionary.

Related

NSMutableDictionary Sorted Keys and Objects did not Creating

I have an array for users, I want create a contact list.
I'm sorting objects and keys alphabetically.
NSArray *sortedKeys = [[contactListDictionary allKeys] sortedArrayUsingSelector: #selector(caseInsensitiveCompare:)];
NSArray *objects = [contactListDictionary objectsForKeys:sortedKeys notFoundMarker:[NSNull null]];
After this, I can initialize dictionary again with sorted keys and
objects.
contactListDictionary = [NSMutableDictionary dictionaryWithObjects:objects forKeys:sortedKeys];
But it did not sorting keys and objects. They are mixing in NSMutableDictionary, what can I do for this situation ?
You can't do anything about this, that is, not in the way you are now trying to.
The NSDictionary class does not allow you to tell it in what order to store its keys; that's just not the way it is implemented.
But you already found out that you can get the keys, in the desired order, in an array. There should be no need for the dictionary itself to be ordered, its purpose is to give you a fast lookup mechanimsm, and it does. If you want, for example, to display the keys in order, simply create a (temporary) array created the way you already now how to.

Objective-C: How to append uniques items from an array to another array?

I have an array and would like to append N items from another array to it, but only the items not already exist in the current array.
Note, the uniqueness of item is determined not by the object memory but its content. For example, I can have two distinct objects called Person with name "David" and I only one of this in my final result.
What's an efficient way to do this? I have looked at the options of doing it using NSPredicate and NSOrderedSet.
[#[arrayOne,arrayTwo] valueForKeyPath:#"#distinctUnionOfArrays.name"] where name is the property to merge the arrays with.
See NSHipster's KVC Collection Operators
Can be easily achieved using NSSet. Here is an example solution:
//Lines of init can be ignored. Just pay attention to the variables and their comments
NSArray * old = [[NSArray alloc]init]; //Assume this is your old array
NSArray * more = [[NSArray alloc]init]; //Assume this is your extra array
NSArray * new = [[NSArray alloc]init]; //Assume this is your new array (having duplicates)
new = [old arrayByAddingObjectsFromArray:more];
NSArray *cleanedArray = [[NSSet setWithArray:new] allObjects];
For explanation, NSSet automatically removes duplicates.
Warning: It does not preserve the order. If you want to proceed to maintain the order, sort it afterwards, or there are more complex solution on the way.

Disable sorting of NSDictionary

I create a NSDictionary, I put there some few objects and keys. But the problem is that the keys is sorted as I understood by the first letters of the key. For example, I put "G", "B", "C". So it is sorting and displaying them as, "B", "C", "G". I would like to disable the sorting, how could I do this. I'm working with more complicated example, but I would like to keep the situation simple in my question.
Question: How I could disable sorting in NSDictionary or how could I sort the NSDictionary myself?
Thanks in advance!
As was stated by #Dan F, NSDictionary does not sort its entries. As was stated in the comment by #Hot Licks, NSDictionary puts its contents in arbitrary order. You should never assume anything about the order of entries in the dictionary. An NSArray is more appropriate for this kind of thing.
If you really want to display the contents of a dictionary in some pre-defined sort order, you can get a array of the keys ordered using the values they are associated with. The NSDictionary class has the keysSortedByValueUsingSelector: and keysSortedByValueUsingComparator: methods that support this. So if you wanted to control the display order by sorting the values into ascending order you could implement do something like this:
NSArray *orderedKeys = [myDictionary keysSortedByUsingSelector:#selector(caseInsensitiveCompare:)];
for (int i = 0; i < [sortedKeys count]; i++) {
NSString *key = [sortedKeys objectAtIndex:i];
NSLog(#"%# = %#", key, [myDictionary objectForKey:key]);
}
The results should show each entry in the dictionary, sorted by the values within each entry.
"Sorting" is not something an NSDictionary knows about, if you want the data to be in a particular order, you should be using an NSArray instead

Appending NSDictionary to other NSDictionary

I have one NSDictionary and it loads up UITableView. If a user scrolls more and more, I call API and pull new data. This data is again in the form of an NSDictionary. Is it possible to add the new NSDictionary to the existing one?
You looking for this guy:
[NSMutableDictionary addEntriesFromDictionary:]
Make sure your UITableView dictionary is an NSMutableDictionary!
Check it here
Use NSMutableDictionary addEntriesFromDictionary to add the two dictionaries to a new mutable dictionary. You can then create an NSDictionary from the mutable one, but it's not usually necessary to have a dictionary non-mutable.
Is your NSDictionary full of other NSDictionaries? It sounds like you would need an NSMutableArray that you could add NSDictionaries to at the end. Assuming you can control the flow of data coming in and wouldn't run the risk of duplicates in your array, you could certainly append the data.
NSMutableArray *array = [[NSMutableArray alloc] init];
arrayCount = [array count]; // check the item count
[array addObject:dictToAppend];
Without seeing how you are implementing it, I can't provide more detailed code examples. Appending items is easy to do, but know it can only be done with mutable versions of Arrays or Dictionaries. Hope this helps a little.

object arranging in NSMutableDictionary

here is my dictionary and its values
NSMutableDictionary *myDic=[NSMutableDictionary Dictionary];
[myDIC setObject:#""];
[myDIC setObject:string1 forKey:key1];
[myDIC setObject:string2 forKey:key2];
[myDIC setObject:string3 forKey:key3];
so up to here i have filled up my dictionary.now i want to read them through a for loop.
for (NSString *key in myDic ){
}
here is my problem! inside this loop the my first key will be key1 but i seems it start from the last key that i have set before!
is there anyone who can tell me why ? and how i can meet my expectation as what i explained?
NSDictionary is not an index base collection it's a Hashtable, and like all HashTable, the elements are store according to some logic base on some Hash that you don't know. If you look in the documentation for NSDictionary you will find a sentence that state that there is not guaranty about the order into which the item will be retrieve.
If you want your key to be retrieve in a specific order you will need to keep your keys in an NSArray, in the order that you want them.
Or you can sort your keys when you need them.
NSArray * allKeys = [myDict allKeys];
allKeys = [allKeys sortedArrayUsing// [see the documentation for all options][1] ];
I came across this problem before. The order of a specific element in NSArray of NSMutableArray is decided by its index.
But unlike NSArray or NSMutableArray,The elements order in NSMutableDictionary or NSDictionary is undefined and nobody knows because its mechanism.
I chose a paragraph from Mac OS X Developer Libary for you:
"Internally, a dictionary uses a hash table to organize its storage
and to provide rapid access to a value given the corresponding key.
However, the methods defined for dictionaries insulate you from the
complexities of working with hash tables, hashing functions, or the
hashed value of keys. The methods take keys directly, not in their
hashed form."