in Objective C - what is the difference between dictionaries and arrays? Are dictionaries used with key : value (where Key can be any object), and arrays are id : value (where id is an integer)?
thanks
Array
In Objective-C, an array is a type of collection which can store object types. It can store any type of objects. Objects stored in an array are linked to their index number.
eg. if you create an array and insert the first object, it will be stored in "index 0"
and, the index number will keep on increasing from 0,1,2....n
Use "NSMutableArray" to create an array that can be modified.
example,
NSMutableArray *array = [NSMutableArray alloc] init];
[array addObject:#"Tom"];
[array addObject:#"Cat"];
So, at index 0, you will have "Tom". And, at index 1, you will have "Cat".
Dictionary
In Objective-C, a dictionary is a type of collection that stores "key-value" pairs.
The "key" is of type ID, so you can enter any object as key for a value.
Use "NSMutableDictionary" to create a dictionary that can be modified.
example,
NSMutableDictionary *dictionary = [NSMutableDictionary alloc] init];
[dictionary setObject:#"Tom" forkey:#"name"];
[dictionary setObject:#"Cat" forKey:#"animal"];
The key difference between array and dictionary is the sequence of the objects gets changed in a dictionary, while in an array the sequence of objects stored is SEQUENTIAL.
[EDIT]
Since there has been quite a discussion with regard to this answer, I will make it clear that the array does NOT get re-created as some comments say.
The size of array/dictionary gets dynamically increased to accomodate the new elements in the colletion.
Related
I'm trying to flatten a two dimensional array of dictionaries with the use of KVC.
NSArray *toBeFlatten = #[#[#{#1:#1}],#[#{#2:#2}]];
NSArray *flat = [toBeFlatten valueForKeyPath:#"#unionOfArrays.self"];
// flat:#[NSNull.null, NSNull.null];
Why are the dictionaries "converted" to NSNull?
It's because valueForKeyPath: also applies to the dictionaries. And how does it work? It looks in each dictionary, tries to use "self" as a key, finds no such key, and returns NSNull to represent the missing value.
To see what I mean, consider this variation on your example:
NSArray *toBeFlatten = #[#[#{#"self":#"hey"}],#[#{#"other":#"ho"}]];
NSArray *flat = [toBeFlatten valueForKeyPath:#"#unionOfArrays.self"];
The result is #[#"hey", NSNull.null] — the value "hey" for the matching key "self" in the first dictionary, and the null because no key matched in the second dictionary.
What you probably meant to say is valueForKeyPath:#"#unionOfArrays.#self" (notice the at-sign, making self an operator, not a key).
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.
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.
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."
how would i go about uniquely naming an object and adding it to an nsmutablearray most likely in a for loop?
You're confusing objects and variables. Variables have names; objects don't unless you give them some name instance variable. More to the point, the same variable can reference different objects at different times. Given some collection of objects collection:
NSMutableArray *array = [NSMutableArray array];
for (id item in collection) {
[array addObject:item];
}
This will create a mutable array with all the objects in collection, with the item variable pointing to a different object from collection on each iteration of the loop.
If you want to uniquely name instances then instead of an array how about using a NSDictionary? Then you can grab the array of keys from it. Run through this key array to get the name of a particular instance and then use that key to get the actual object instance from the dictionary.