Let's say the name of dictionary is nameOfDictionary and the key name is string.
I was trying to get the value of the dictionary by using:
[nameOfDictionary objectForKey:#"string"];
However, I was getting the one at the bottom. Is there anyway I can get the 222 or sample alone?
{
222 = "sample";
}
It appears that the object under the "string" key is also a dictionary. So you can do this to get the key and value of that dictionary separately.
NSDictionary *nameOfDictionary = #{#"string":#{#"222":#"Sample"}};
NSDictionary *dict = nameOfDictionary[#"string"];
for (NSString *key in [dict keyEnumerator]) {
NSLog(#"%# = %#", key, dict[key]);
}
key will contain 222 and dict[key] will contain sample
Try allKeys function will return all keys,
for( NSString *aKey in [dictionary allKeys])
{
NSLog(#"Do something with the key here:%#",aKey );
}
Related
I am working on an iOS app, where I will be getting a JSON Object from server, which will be populated on a UITableView.
User can change values on tableview, Hence resulting in a new JSON.
Now I want to send only delta (Difference of Two JSON Objects) back to server.
I know I can traverse both Objects for finding delta. But just wish to know is there any easy solution for this problem.
Ex:
NSDictionary *dict1 = {#"Name" : "John", #"Deptt" : #"IT"};
NSDictionary *dict2 = {#"Name" : "Mary", #"Deptt" : #"IT"};
Delta = {#"Name" : "Mary"}
Considering new value is Mary for key name;
Thanks In Advance
isEqualToDictionary: Returns a Boolean value that indicates whether the contents of the receiving dictionary are equal to the contents of another given dictionary.
if ([NSDictionary1 isEqualToDictionary:NSDictionary2) {
NSLog(#"The two dictionaries are equal.");
}
Two dictionaries have equal contents if they each hold the same number of entries and, for a given key, the corresponding value objects in each dictionary satisfy the isEqual: test.
Here's how to get all the keys with non-matching values. What to do with those keys is app level question, but the most informative structure would include an array of mismatched values from both dictionaries, as well has handle keys from one that are not present in the other:
NSMutableDictionary *result = [#{} mutableCopy];
// notice that this will neglect keys in dict2 which are not in dict1
for (NSString *key in [dict1 allKeys]) {
id value1 = dict1[key];
id value2 = dict2[key];
if (![value1 equals:value2]) {
// since the values might be mismatched because value2 is nil
value2 = (value2)? value2 : [NSNull null];
result[key] = #[value1, value2];
}
}
// for keys in dict2 that we didn't check because they're not in dict1
NSMutableSet *set1 = [NSMutableSet setWithArray:[dict1 allKeys]];
NSMutableSet *set2 = [NSMutableSet setWithArray:[dict2 allKeys]];
[set2 minusSet:set1]
for (NSString *key in set2) {
result[key] = #[[NSNull null], dict2[key]];
}
There are certainly more economical ways to do it, but this code is optimized for instruction.
Just enumerate through and compare the dictionaries key-by-key. This will output any differences as well as any unmatched keys on either side, you can tweak the logic depending on exactly what you want to include.
- (NSDictionary *)delta:(NSDictionary *)dictionary
{
NSMutableDictionary *result = NSMutableDictionary.dictionary;
// Find objects in self that don't exist or are different in the other dictionary
[self enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
id otherObj = dictionary[key];
if (![obj isEqual:otherObj]) {
result[key] = obj;
}
}];
// Find objects in the other dictionary that don't exist in self
[dictionary enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
id selfObj = self[key];
if (!selfObj) {
result[key] = obj;
}
}];
return result;
}
I have one NSDictionary and in that dictionary keys and values are dynamically added.Now I want to check if any value is nil then set empty string for that key.How can I check this? Now I am checking this using conditions but, Is there any simple way to check nil or empty values.Please help me,Thanks
NSDictionary does not hold nil values for its keys.
If you want to test the presence/absence of a specific key's value, you can use -objectForKey:. The method returns nil if the key/value pair is absent.
For "empty values", you will have to expand on what is considered an empty value in the context of your program (e.g. some people use NSNull to indicate an empty value, or if you are working with strings as values an empty string).
For any key you haven’t set a value for, your dictionary will return nil from -objectForKey:—in other words, if nothing’s set for a given key, that key doesn’t exist in the dictionary.
That said, it sounds like you have a list of keys that you’d like to ensure have a placeholder value in the dictionary, with that placeholder value being an empty string. For that, you’d want to do something like this:
- (void)addPlaceholdersForKeys:(NSArray *)keys toDictionary:(NSMutableDictionary *)dictionary {
for (id key in keys) {
if ([dictionary objectForKey:key] == nil) {
[dictionary setObject:#"" forKey:key];
}
}
}
NSDictionary and other collections cannot contain nil values. But it must store a null value. You can check it like that:-
if (dictionary[key] == [NSNull null]) {
[dictionary setObject:#"" forKey:key];
}
For more refer sample code:-
NSMutableDictionary *dict=[NSMutableDictionary dictionary];
[dict setObject:#"test" forKey:#"key1"];
[dict setObject:#"test1" forKey:#"key2"];
[dict setObject:[NSNull null] forKey:#"key3"];
NSLog(#"%#",dict);
if (dict[#"key3"]==[NSNull null])
{
[dict setObject:#"" forKey:#"key3"];
NSLog(#"%#",dict);
}
Output:-
Before setting empty value:-
{
key1 = test;
key2 = test1;
key3 = "<null>";
}
After setting empty value:-
{
key1 = test;
key2 = test1;
key3 = "";
}
you can do like this by looping through the dictionary
NSArray *keys = [dictionary allKeys];
for(NSString *key in keys)
{
if ([dictionary objectForKey:key] == NULL)
{
[dictionary setObject:#"" forKey:key];
}
}
How can i loop through the following dictionary obtained from JSON? How can i loop to get only the id 0001, 0002?
{
0001 = {
userName = "a";
photo = "";
};
0002 = {
userName = "b";
photo = "";
};
}
You loop thru the NSDictionary keys:
NSArray *keys = [dictionary allKey];
for (id *key in keys ) {
NSDictionary *userPhoto = [dictionary objectForKey:key];
// here you can either parse the object to a custom class
// or just add it to an array.
}
Or use the fast enumeration directly on the NSDictionary:
for (id *key in dictionary ) {
NSDictionary *userPhoto = [dictionary objectForKey:key];
// here you can either parse the object to a custom class
// or just add it to an array.
}
Per key you can retrieve the object.
or use the enumerateKeysAndObjectsUsingBlock:
[dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
// Here you can access the object and key directly.
}
Try this way...
Get all keys
NSArray *a=[yourDictionary allKeys];
NSArray *keys = [dictionary allKeys];
Try this. You will get all keys in an array. And then you can get them in NSString accordingly .
Another alternative is using the enumerateKeysAndObjectsUsingBlock: api to enumerate the keys and objects,
Usage is pretty simple,
[dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
NSLog(#"Key: %#, Value:%#",key,obj);
if([key isEqualToString:#"0001"]) {
//Do something
}
// etc.
}];
Hope that helps!
I found the answer. I already tried with the following code but it is giving all the data.
Because the json i got is in the worng format.
for (NSString *key in Dict) {}
I have a dictionary with key-value pair populated from JSON returned data.What I wish to do is use the dictionary to populate UITableView.
I have this structure for table:
[Product Name]
By [Manufacturer Name]
What this means is that key is Product Name and Value is Manufacturer Name. I need to get the name of the key and the name of the value. How can this be done? and is it possible without for-loop?
I'd use the enumerateKeysAndObjectsUsingBlock: method. The following code builds a list of the strings you require.
NSMutableArray *names = [NSMutableArray array];
[dictionary enumerateKeysAndObjectsUsingBlock: ^(NSString *key, NSString *object, BOOL *stop) {
[names addObject[NSString stringWithFormat:#"%# By %#",key, object]];
}];
You can use the keyEnumerator of NSDictionary and for each key look up the value. This could look something like this:
for (NSString *p in dict)
{
NSString *m = [dict objectForKey:p];
// do something with (p,m)
}
You should not be concerned with avoiding for-loops. After all, something like a for loop will always happen somewhere underneath.
If your keys are dynamic from json then you can use
NSArray *keys = [dictionary allkeys];
Then in the table View Cell for row at index path method you can populate the table view with the corresponding keys and their values.
NSArray * keys = [results allKeys];
for (int i = 0;i<[keys count];c++){
NSString* productName = [key objectAtIndex:i];
NSString* manufacturerName = [results objectForKey:productName];
}
Hope this helps...
I have assumed the name as strings, you can change the type according to your situation..
I've been trying to merge two NSDictionaries for a couple hours now. Searched and found that I can use [NSMutableDictionary addEntriesFromDictionary:].
NSDictionary *areaAttributes = [[area entity] attributesByName];
NSDictionary *gpsAttributes = [[gps entity] attributesByName];
NSMutableDictionary *areaAttributesM = [areaAttributes mutableCopy];
NSMutableDictionary *gpsAttributesM = [gpsAttributes mutableCopy];
NSMutableDictionary *combinedAttributes = [areaAttributesM addEntriesFromDictionary:gpsAttributesM];
But I get the error:
Initializing 'NSMutableDictionary *_strong' with an expression of incompatible type 'void'
So this is saying that [areaAttributesM addEntriesFromDictionary:gpsAttributesM] returns void? Is my understanding correct? And why is it returning void?
Yes, you are correct. From the docs:
- (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary
As to why, that's simple: Functions that mutate an object in place in Cocoa usually return void, so you can easily distinguish them from functions that return a different object.
Also, there's no reason to mutableCopy the gpsAttributes dictionary; it's just being used as the argument to -[addEntriesFromDictionary:], which doesn't need to be mutable.
So, the right way to do this is:
NSDictionary *areaAttributes = [[area entity] attributesByName];
NSDictionary *gpsAttributes = [[gps entity] attributesByName];
NSMutableDictionary *combinedAttributes = [areaAttributes mutableCopy];
[combinedAttributes addEntriesFromDictionary:gpsAttributes];
You may want to wrap this up in a function (or a method in a category on NSDictionary), if you do if often:
NSDictionary *mergeDictionaries(NSDictionary *lhs, NSDictionary *rhs) {
NSMutableDictionary *ret = [lhs mutableCopy];
[ret addEntriesFromDictionary:rhs];
return ret;
}
From the Documentation, addEntriesFromDictionary tells that:
If both dictionaries contain the same key, the receiving dictionary’s previous value object for that key is sent a release message, and the new value object takes its place.
You need to use setObject to add each object to the dictionary.YOu need to loop through the keys of one dictionary and add it to the final dictionary.
Even setObject tells the same:
The key for value. The key is copied (using copyWithZone:; keys must conform to the NSCopying protocol). If aKey already exists in the dictionary, anObject takes its place.
You cannot have two same keys in the dictionary. All keys in the dictionary are unique.
If you still want to have the same key-value in the dictionary, you must use a different key.
For example, you have two dictionaries with following values:
NSDictionary *dict1=#{#"hello":#"1",#"hello2" :#"2"};
NSDictionary *dict2=#{#"hello":#"1",#"hello2":#"2",#"hello3":#"1",#"hello6":#"2",#"hello4":#"1",#"hello5" :#"2"};
NSMutableDictionary *mutableDict=[NSMutableDictionary dictionaryWithDictionary:dict1];
for (id key in dict2.allKeys){
for (id subKey in dict1.allKeys){
if (key==subKey) {
[mutableDict setObject:dict2[key] forKey:[NSString stringWithFormat:#"Ext-%#",key]];
}else{
[mutableDict setObject:dict2[key] forKey:key];
}
}
}
and by the end of this loop, your new mutable dictionaries will have the follwoing key-values:
{
"Ext-hello" = 1;
"Ext-hello2" = 2;
hello = 1;
hello2 = 2;
hello3 = 1;
hello4 = 1;
hello5 = 2;
hello6 = 2;
}
As you can see, hello, and hello2 keys are renamed as Ext-hello1, Ext-hello2. form the dict1, and you still have all the dict2 values added to your mutable dict.
IF you don't want to add a new key, then you can add the values into an arrya and add that array to the dictionary. YOu can modify the for-loop to:
for (id key in dict2.allKeys){
for (id subKey in dict1.allKeys){
if (key==subKey) {
NSMutableArray *myArr=[[NSMutableArray alloc]init];
[myArr addObject:dict1[subKey]];
[myArr addObject:dict2[key]];
[mutableDict setObject:myArr forKey:key];
}else{
[mutableDict setObject:dict2[key] forKey:key];
}
}
}
And now you will have the values merged into an array:
{
hello = (
1,
1
);
hello2 = 2;
hello3 = 1;
hello4 = 1;
hello5 = 2;
hello6 = 2;
}
In this way, the number of keys will be same, and the values for the same key will be added as an array.