Get list of all leaves from NSDictionary - ios

I have an NSDictionary that contains more dictionaries. The final dictionary's value (leaf) is an array containing some data. The depth to each leaf is unknown.
I attempted to write recursive function to combine all the arrays that are children of the level 0 key.
Here's what I have so far:
- (NSArray *)getAllDictArrays:(NSDictionary *)dictionary WithKey:(NSString *)key
{
if ([[dictionary objectForKey:key] isKindOfClass:[NSArray class]]) {
// grab array and save for later or append to global array and return later
} else {
NSDictionary *newDict = [dictionary objectForKey:key];
NSString *newKey;
for (newKey in newDict.allKeys) {
//NSLog(#"Calling Key: %#", newKey);
[self getAllDictArrays:newDict WithKey:newKey];
}
}
return ???;
}

Related

objectForKey throws an exception on count if it contains a single value

I have a dictionary JSON dictionary like
{
county = "XXXXX";
states = (
"YYYYY",
"ZZZZZ"
);
}
After reading the JSON dictionary the data is in an array. I then want to create a different array with the data and I am using the following code
for (NSString *key in array) {
NSMutableArray *myData =[[NSMutableArray aalloc] init];
myData = [array objectForKey:key];
int count = [myData count];
}
When key is 'states', it works fine. If key is 'country', then it throws an exception on count because objectForKey returns a NSString. How to resolve this? How to find how many objects the objectForKey will return?
Check out this answer from #HDdeveloper:
if([object isKindOfClass:[NSString class]] == YES)
{
NSLog(#"String rx from server");
}
else if ([object isKindOfClass:[NSDictionary class]] == YES)
{
NSLog(#"Dictionary rx from server");
}
else if ([object isKindOfClass:[NSArray class]] == YES)
{
NSLog(#"Array rx from server");
}
Basically, after you get the objectForKey, then you need to check what kind of object that is and use it accordingly.
Your JSON contains a dictionary.
The key "states" in that dict contains an array, and the other key contains a string. Neither key contains an NSData object.
Arrays have a count method, but strings do not. That's why you're crashing.

Finding distinct array elements based on dictionary key

I have two arrays of key-value pairs. Both these arrays contain different key-value pairs. I want to find elements in the first array that are not part of the second array based on a particular key.
Example:
1st Array - [{id=1, name="foo"},
{id=2, name="bar"}]
2nd Array - [{id=2, name="abc"},
{id=1, name="xyz"}]
Is there a way I can implement the same?
Right now I enumerate through the two arrays like so:
for (NSDictionary *eachPlayer in 1stArray) {
for (NSDictionary *eachPrediction in 2ndArray) {
if (eachPrediction[kId] != eachPlayer[kId]) {
[self.predictPlayerArray addObject:eachPlayer];
}
}
}
But this fails in the above case and adds both the values to the predictionPlayerArray - in the first iteration it adds 1 and in the forth iteration it adds 2. How do I prevent that from happening?
Thanks.
EDIT
I seem to have solved it this way. Not the best solution but it seems to be working:
for (NSDictionary *eachPlayer in arrayOne) {
for (NSDictionary *eachPrediction in arrayTwo) {
if (eachPrediction[kId] == eachPlayer[kId]) {
if ([self.predictPlayerArray containsObject:eachPlayer]) {
[self.predictPlayerArray removeObject:eachPlayer];
}
break;
}
else {
[self.predictPlayerArray addObject:eachPlayer];
}
self.predictPlayerArray = [self.predictPlayerArray valueForKeyPath:#"#distinctUnionOfObjects.self"];
}
}
Something like this should do:
NSArray *array1 = #[#{#"1":#"foo"},#{#"2":#"bar"},#{#"3":#"abc"}];
NSArray *array2 = #[#{#"2":#"abc"},#{#"1":#"abc"},#{#"4":#"foo"}];
NSMutableSet *result = [NSMutableSet new];
for (NSDictionary *dict1 in array1){
[dict1 enumerateKeysAndObjectsUsingBlock:^(id key1, id obj1, BOOL *stop1) {
for (NSDictionary *dict2 in array2) {
[dict2 enumerateKeysAndObjectsUsingBlock:^(id key2, id obj2, BOOL *stop2) {
if ([obj2 isEqual:obj1]){
[result addObject:#{key1:obj1}];
*stop2 = YES;
}
}];
}
}];
}
NSLog(#"result %#", result);
As you has nested dictionaries you should iterate also in them and finally store the result in a set that would prevent to have duplicate entries (if you use a NSMutableArray you will have twice {3:abc})
The log output is:
2015-02-03 13:53:07.897 test[19425:407184] result {(
{
1 = foo;
},
{
3 = abc;
}
)}

Xcode - How to combine key and value into single array?

I have a JSON array being pulled into XCode with a key and value. I can get the keys. I can get the values. But is there an easy way to combine them into a single array?
The following code works, but I end up with two separate arrays (channels and channelKeys).
This seems like an inelegant way to create a single array which contains both the key and its value.
-(void) convertArray : (NSMutableArray *)data{
// Set data
NSMutableDictionary *dic = [data objectAtIndex:0];
for (NSString *key in [dic allKeys]) {
[channels addObject:[dic objectForKey:key]];
}
// Set Key Array
NSMutableDictionary *dic3 = [data objectAtIndex:0];
NSArray *keys = [dic3 allKeys];
[channelKeys addObjectsFromArray: keys];
}
If you are trying to create an array of the form [key1, value1, key2, value2, key3, value3...] then try something like the following (recall that keys are not restricted to NSStrings)
for (id key in [dic allKeys]) {
[resultArray addObject:key];
[resultArray addObject:[dic objectForKey:key]];
}

Search element in nsdictionary by value

I have nsdictionary which contains elements with following structure
name --> value
email--> key
I get value(of above structure) from user,
now I want to search element in nsdictionary by value(entered by user) not by key, whether it is present in nsdictionary or not and also want to get index of that element if present.
How to do this?
The best to do so would propably be
- (NSArray *)allKeysForObject:(id)anObject
This method of NSDictionary gives you back all the keys having anObject as their value. If you only have each object once in the whole dictionary it will logically return an array with only one key in it.
NSArray * users = ...; //your array of NSDictionary objects
NSPredicate *filter = [NSPredicate predicateWithFormat:#"email = test#gmail.com"];
NSArray *filteredContacts = [contacts filteredArrayUsingPredicate:filter];
for more than one value of email, then use an OR in the predicate:
filter = [NSPredicate predicateWithFormat:#"contact_type = 42 OR contact_type = 23"];
The dictionary data structure has no 'order', so you'd have to search for your key by iterating the collection and looking for the desired value.
Example:
NSString *targetKey = nil;
NSArray *allKeys = [collection allKeys];
for (int i = 0; i < [allKeys count]; ++i) {
NSString *key = [allKeys objectAtIndex:i];
NSString *obj = [collection objectForKey:key];
if ([obj isEqualToString:searchedString]) { // searchedString is what you're looking for
targetKey = key;
break;
}
}
// check if key was found (not nil) & proceed
// ...
You can search the entered value in NSDictionary , but you can't get an index of value , as NSDictionary has no order of key value pair.
NSArray *array = [yourDictionaryObject allValues];
if ([array containsObject:#"userEnteredValue"]) {
<#statements#>
}
You need to iterate through the Dictionary for the keys has the Value of your need:
Try this:
NSArray *keys= [json allKeys];
for (NSString *keysV in keys){
NSLog(#"Keys are %#", keysV);
if([Your_Dict objectForKey: keysV] isEqual:#"string to Match"){
//Do your stuff here
}
}

How to loop NSDictionary obtained from JSON?

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) {}

Resources