xcode - set value of a nested object - ios

I have a json from a service and I need to change the values of one obeject.
{
question = (
{
answer = (
{
Id = 1;
value = 1;
},
{
Id = 2;
value = 0;
}
);
},
.....
I use that code to directly access to the second "value" element and set it to "true"
NSMutableDictionary * dict = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
NSMutableDictionary *preguntasDict = [[NSMutableDictionary alloc] init];
preguntasDict =[[[dict valueForKey:#"question"]mutableCopy];
NSMutableDictionary *answer = [[NSMutableDictionary alloc] init];
respuestasDict =[[[[preguntasDict valueForKey:#"answer"]objectAtIndex:0]objectAtIndex:1] mutableCopy];
[respuestasDict setObject:[NSNumber numberWithBool:true] forKey:#"value"];
It works: "respuestasDict" changes but the whoole "dict" not.
My question is: how could rebuild the entire dictionary? or it is possible to access directly to the nested object and change it?

Note that perguntasDict and respuestasDict are mutable copies of your dictionaries, so basically you are editing copies of your dict. You need to access dict directly, like this:
NSArray *answers = dict[#"question"][#"answer"];
[answers firstObject][#"value"] = #(YES);
PS: Doing dict[#"question"] is the same thing as [dict objectForKey:#"question"]. Also, #(YES) is the same thing as [NSNumber numberWithBool:true]

Related

How to Convert NSMutableArray to NSMutableDictionary

In objective c how to convert NSMutableArray to NSMutableDictionary I tried with this code.but only last index object only adding in the dictionary.
I need the format like this
ADDRESS =
{
major = 604;
minor = 37940;
uuid = "xxxxxxx";
};
{
major = 604;
minor = 37940;
uuid = "xxxxxxxxx";
};
{
major = 604;
minor = 37940;
uuid = "xxxxxxxxxx";
};
I tried with this code
NSMutableDictionary * dic1 = [NSMutableDictionary dictionary];
for (int j = 0; j <[self.beaconListArray count]; j ++)
{
[dic1 setObject:[self.beaconListArray objectAtIndex:j] forKey:#"ADDRESS"];
}
Try like this , Because you're dictionary is overiding object and you have already array of your data and you need to create dictionary using that for address key
NSMutableDictionary * dic1 = [NSMutableDictionary dictionary];
[dic1 setObject:self.beaconListArray forKey:#"ADDRESS"];
Use this.
NSMutableDictionary * dic1 = [NSMutableDictionary new];
dic1[#"ADDRESS"] = self.beaconListArray;
You can try to this code
Dictionary
NSMutableDictionary * dic1 = [NSMutableDictionary dictionary];
Add Dictionary to array with key
[dic1 setObject:self.beaconListArray forKey:#"ADDRESS"];
Print Dictionary
NSLog(#"dic1====: %#",dic1);

how to get nsDictionary element by using for-in

NSDictionary *myDict = #{#"one":#"1",#"two":#"2"};
for (NSDictionary* tmp in myDict) {
NSLog(#"%#",tmp);
}
resut:
my tmpis NSString
I want to get a dictionary with key= one , value = 1
for in for NSDictionary will iterate the keys.
for (NSString * key in myDict) {
NSLog(#"%#",key);
NSString * value = [myDict objectForKey:key];
}
If you want to get a dictionary. You have to create a dictionary from these values
for (NSString * key in myDict) {
NSLog(#"%#",key);
NSString * value = [myDict objectForKey:key];
NSDictionary * dict = #{key:value};
}
Or you should init like this:
NSArray *arrDict = #[{#{"one":#"1"},#{#"two":#"2"}];
for (NSDictionary* tmp in arrDict) {
NSLog(#"%#",tmp);
}
You can get all keys from your dic then add the key and value to your new dic like this:
NSDictionary *myDict = #{#"one":#"1",#"two":#"2"};
NSArray *keys = [myDict allKeys];
for (NSString *key in keys) {
NSDictionary *yourDic = #{key: [myDict valueForKey:key]};
NSLog(#"%#", yourDic);
}
You didn't create it that way. If you wanted to have a NSDictionary inside another NSDictionary you should write something like this :
NSDictionary *myDict = #{
#"firstDict" : #{
#"one":#"1"
},
#"secondDict": #{
#"two":#"2"
}
};
Above code will create a NSDictionary with two dictionaries at keys #firstDict and #secondDict.
Also, bear in mind, that because dictionaries are key-value pairs, using a for-in loop, actually loops through the keys in that dictionary. So your code is equivalent to:
for(NSString *key in dict.allKeys) { ... }
I got the solution
NSDictionary *myDict = #{#"one":#"1",#"two":#"2"};
NSMutableArray *arrayObject = [[NSMutableArray alloc]init];
NSMutableArray *arrayKey = [[NSMutableArray alloc]init];
NSMutableArray *arrayObjectKey = [[NSMutableArray alloc]init];
NSMutableDictionary *dict = [[NSMutableDictionary alloc]init];
for (NSString *stringValue in myDict.allValues)
{
[arrayObject addObject:stringValue];
}
for (NSString *stringKey in myDict.allKeys)
{
[arrayKey addObject:stringKey];
}
for(int i = 0;i<[arrayKey count];i++)
{
dict = [[NSMutableDictionary alloc]initWithObjectsAndKeys:[NSString stringWithFormat:#"%#",[arrayKey objectAtIndex:i]],#"key",nil];
[dict setObject:[NSString stringWithFormat:#"%#",[arrayObject objectAtIndex:i]] forKey:#"value"];
[arrayObjectKey addObject:dict];
}
NSLog(#"The arrayObjectKey is - %#",arrayObjectKey);
The Output is
The arrayObjectKey is -
(
{
key = one;
value = 1;
},
{
key = two;
value = 2;
}
)
Create the dictionary:
NSDictionary *myDict = [NSDictionary dictionaryWithObjectsAndKeys:#"1",#"One",#"2","Two",nil];
Get a value out using:(this example tmp will be 1)
NSString *tmp = [myDict objectForKey:#"One"];
Display the output in console:
NSLog(#"%#",tmp);
To display the whole NSDictionary
NSLog (#"contents of myDict: %#",myDict);
What you are doing is creating a dictionary with key-value pairs. I think what you want to do is have an array with dictionaries.
NSArray *myArray = #[#{#"one":#"1"}, #{#"two":#"2"}];
for (NSDictionary* tmp in myArray) {
NSLog(#"%#",tmp);
}
However I don't see a point in doing this. What you could do is:
NSDictionary *myDict = #{#"one":#"1",#"two":#"2"};
for (NSString* key in [myDict allKeys]) {
NSLog(#"%# = %#", key, myDict[key]);
}

how to group array of nsdictionary according to the value inside the element

I have array of dictionary that needs to be grouped according to PO which is part of the element and also get the total of quantityOrdered according to the same PO.
The PO is dynamic it means it can be any value that needs to be filtered and compute the quantityOrderd accordingly.
Please help.
{
PO = PO2;
QuantityReceived = 1;
},
{
PO = PO1;
QuantityReceived = 3;
},
{
PO = PO1;
QuantityReceived = 3;
},
{
PO = PO3;
QuantityReceived = 2;
},
{
PO = PO2;
QuantityReceived = 2;
},
{
PO = PO3;
QuantityReceived = 4;
},
{
PO = PO1;
QuantityReceived = 1;
},
Apology for the confusion or incomplete question but i need to create a new array of dictionary with similar like this :
{
PO = PO1;
TotalQuanityReceived=7;
LineItems=3;
},
{
PO = PO2;
TotalQuanityReceived=3;
LineItems=2;
},
{
PO = PO3;
TotalQuanityReceived=6;
LineItems=2;
},
i updated my example and make it easy to read.
- (NSArray *)whatever:(NSArray *)dictionaries
{
NSMutableArray *results = [[NSMutableArray alloc] init];
NSMutableDictionary *resultsByPO = [[NSMutableDictionary alloc] init];
for (NSDictionary *dictionary in dictionaries) {
id po = [dictionary objectForKey:#"PO"];
NSMutableDictionary *result = [resultsByPO objectForKey:po];
if (result == nil) {
result = [[NSMutableDictionary alloc] init];
[resultsByPO setObject:result forKey:po];
[results addObject:result];
[result setObject:po forKey:#"PO"];
}
double total = [[result objectForKey:#"TotalQuantityReceived"] doubleValue];
total += [[dictionary objectForKey:#"QuantityOrdered"] doubleValue];
int count = 1 + [[result objectForKey:#"Count"] intValue];
[result setObject:#(total) forKey:#"TotalQuantityReceived"];
[result setObject:#(count) forKey:#"Count"];
}
return results;
}
More pain will come with PO values not conforming to NSCopying.
You can do it the clever way with KVC or the stupid easy way. Let's do it the stupid easy way!
Make an empty NSMutableDictionary. Let's call it dict.
Cycle through your array of dictionaries. For each dictionary:
Fetch its PO. Call that value thisPO.
Fetch dict[thisPO]. Was it nil?
a. Yes. Okay, so this particular PO has not yet been encountered. Set dict[thisPO] to this dictionary's quantity received (as an NSNumber).
b. No. Turn that value into an integer, add this dictionary's quantity received, and set the total back into dict[thisPO] (as an NSNumber).
Done! The result is not quite what you asked for; the result looks like this:
{
PO1 = 100;
PO2 = 120;
...
}
But now, you see, the work of totalling is done and it is easy to transform that into an array of dictionaries if that is what you want.
Not 100% sure if this is what you are saying or not, but to sort an array of dictionaries based on one of the elements it would look something like this.
NSDictionary *d1 = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithDouble:100],#"PO",
[NSNumber numberWithDouble:0], #"Category",
nil];
NSDictionary *d2 = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithDouble:50],#"PO",
[NSNumber numberWithDouble:90], #"Category",
nil];
NSArray *unsorted = #[d1, d2];
NSArray *sortedArray;
sortedArray = [unsorted sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
NSDictionary *first = (NSDictionary*)a;
NSDictionary *second = (NSDictionary*)b;
NSNumber *firstPO = [first objectForKey:#"PO"];
NSNumber *secondPO = [second objectForKey:#"PO"];
return [firstPO compare:secondPO];
}];
NSLog(#"unsorted = %#", unsorted);
NSLog(#"sorted = %#", sortedArray);
I wasn't really sure what PO was, so I just used an NSNumber as an example. Look at this page for an overview of how you would compare a customer object. http://nshipster.com/nssortdescriptor/.
Then you can loop through the array, now in the correct order and build your next NSDictionary.

Get a value from nsdictionary

I want to give a key value from my NSDictionary and get the value associated to it.
I have this:
NSArray *plistContent = [NSArray arrayWithContentsOfURL:file];
NSLog(#"array::%#", plistContent);
dict = [plistContent objectAtIndex:indexPath.row];
cell.textLabel.text = [dict objectForKey:#"code"];
with plistContent :
(
{
code = world;
key = hello;
},
{
code = 456;
key = 123;
},
{
code = 1;
key = yes;
}
)
So how do I get "hello" by giving the dictionary "world"?
If I understand your question correctly, you want to locate the dictionary where "code" = "world" in order to get the value for "key".
If you want to keep the data structure as it is, then you will have to perform a sequential search, and one way to do that is simply:
NSString *keyValue = nil;
NSString *searchCode = #"world";
for (NSDictionary *dict in plistContents) {
if ([[dict objectForKey:#"code"] isEqualToString:searchCode]) {
keyValue = [dict objectForKey:#"key"]); // found it!
break;
}
}
However if you do alot of this searching then you are better off re-organizing the data structure so that it's a dictionary of dictionaries, keyed on the "code" value, converting it like this:
NSMutableDictionary *dictOfDicts = [[NSMutableDictionary alloc] init];
for (NSDictionary *dict in plistContents) {
[dictOfDicts setObject:dict
forKey:[dict objectForKey:#"code"]];
}
(note that code will break if one of the dictionaries doesn't contain the "code" entry).
And then look-up is as simple as:
NSDictionary *dict = [dictOfDicts objectForKey:#"world"]);
This will be "dead quick".
- (NSString*) findValueByCode:(NSString*) code inArray:(NSArray*) arr
{
for(NSDictonary* dict in arr)
{
if([[dict valueForKey:#"code"] isEqualToString:code])
{
return [dict valueForKey:#"key"]
}
}
return nil;
}

NSDictionary adding multiple keys

May I know is that possible for NSDictionary or NSMutableDictionary to add in multiple same keys for different object? It is because of the API that written by the developers are accepting an array.
e.g:
NSArray *ids = #[#"xxx", #"yyy", #"zzz"];
NSMutableDictionary *args = [[NSMutableDictionary alloc] initWithObjectsAndKeys:#"someobject", #"somekey"];
I've defined an args and set of ids that picked by user and now I will loop the array.
for( NSString *getId in ids ){
[args setObject:getId forKey:#"ids[]"];
}
So ended up, the results come out are
"somekey" = "someobject", "ids[]" = "zzz";
Is that possible for me to get result as follows?
"somekey" = "someobject", "ids[]" = "xxx", "ids[]" = "yyy", "ids[]" = "zzz";
Please advise, thanks!
Yes it is possible
NSArray *arr = [[NSArray alloc]initWithObjects:#"xxx",#"yyy",#"zzz", nil];
NSMutableDictionary *dic = [[NSMutableDictionary alloc] initWithObjectsAndKeys:#"Someobject", #"Somekey", nil];
for (int i = 0; i<[arr count]; i++) {
[dic setValue:[arr objectAtIndex:i] forKey:[NSString stringWithFormat:#"id[%d]", i]];
}
NSLog(#"dic %#",dic);
Use this code sure it would help you.
No, key is unique. But you can put an NSMutableArray in your NSDictionary, and store you values like key => array(x,y,...)
Instead of that you can create Dictionary like this.
YourDictionary = {
"somekey" = "someobject",
"ids[]" = (
"xxx",
"yyy",
"zzz"
)
}
Treat ids[] as an array
Hope this will solve your problem
No that's not the way a dictionary should be used. As peko said, just put your array in the dict:
[args setObject:ids forKey:#"ids"];

Resources