I've populated a uitableview from an NSMutableDictionary using this code to populate my dictionary:
-(NSMutableDictionary *)createDictionaryForSectionIndex:(NSArray *)array withSubtitle:(NSArray *)subtitle
{
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
for (char firstChar = 'a'; firstChar <= 'z'; firstChar++)
{
NSString *firstCharacter = [NSString stringWithFormat:#"%c", firstChar];
NSArray *content = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF beginswith[cd] %#", firstCharacter]];
NSMutableArray *mutableContent = [NSMutableArray arrayWithArray:content];
if ([mutableContent count] > 0)
{
NSString *key = [firstCharacter uppercaseString];
[dict setObject:mutableContent forKey:key];
NSLog(#"%#: %lu", key, (unsigned long)[mutableContent count]);
}
NSLog(#"mutable content: %#", mutableContent);
}
return dict;
}
from this source: https://stackoverflow.com/a/13279408/1042801
I'm trying to add another key/value for each outputted key/value. It's somewhat difficult to articulate my thoughts, so here's an example of something that I think I need:
key => 'A'
object => {"Aardvark"
object => {"mammal"}
, "Ape"
object => {"mammal"}
, "Aquaman"
object => {"superhero"}
}
//etc...
My table view should then be able to access those keys for each object above it to use as a detail text label for the cells in my table view. My apologies if what I'm trying to accomplish makes no sense, dictionaries aren't quite engrained in my repertoire yet.
Related
After a network call to the Instagram API, I get back a responseDictionary NSDictionary delegate with the following Key/Value structure:
{
data = (
{
bio = "Los Angeles/Orange County Realtor\U00ae \n\U6d1b\U6749\U77f6\U623f\U5730\U4ea7\U7ecf\U7eaa\U4eba\nCall/Text/WhatsApp: (310) 717-1321\nEmail: Jxxxcom\nWeChat (\U5fae\U4fe1): xx";
"full_name" = "xx yy (\U7530\U4f73\U6dfc) Rx Realty";
id = 25354408;
"profile_picture" = "http://scontent-a.cdninstagram.com/hphotos-xpa1/outbound-distillery/t0.0-20/OBPTH/profiles/profile_xxx_75sq_1391378894.jpg";
username = jxxi;
website = "http://www.Jxghty.com";
},
The profile_picture key often has an NSString value that contains anonymousUser (for the users who didn't set any profile pictures).
I am looking to remove those entries from my responseDictionary as follows:
//Create mutable copy of IG responseDictionary
NSMutableDictionary *dictCleanAvatars = [responseDictionary mutableCopy];
NSLog(#"Log dictCleanAvatars after mutableCopy IG response: %#", dictCleanAvatars);
NSArray *keys = [dictCleanAvatars allKeys]; //get all the keys
NSUInteger k2 = [dictCleanAvatars count];
NSLog(#"k2 in dictCleanAvatars before cleanup is: %lu", (unsigned long)k2);
for (int i = 0; i<k2; i++)
{
if ([[dictCleanAvatars objectForKey:[keys objectAtIndex:i]] isKindOfClass:[NSString class]])
{
//if its an NSString - don't want an exception if its another type of object
NSLog(#"Yes, objectAtIndex:i us Kind ofClass NSString for i = %d", i);
if ([[dictCleanAvatars objectForKey:[keys objectAtIndex:i]] rangeOfString:#"anonymousUser"].location != NSNotFound)
{
NSLog(#"Yes, anonymousUser identified in objectAtIndex:i for i = %d", i);
//if object has the key word im looking for
[dictCleanAvatars removeObjectForKey:[keys objectAtIndex:i]]; //remove the key
NSLog(#"That's dictCleanAvatars after loop %d: %#", i, dictCleanAvatars);
}
}
}
But this doesn't work.
Would value feedback from more experience iOS developers.
If you're trying to build an array that includes everything from the data key's array, but omitting those dictionaries for which profile_picture contains the string "AnonymousUser", you can use NSPredicate:
NSArray *dataArray = responseDictionary[#"data"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"not (profile_picture contains 'AnonymousUser')"];
NSArray *filteredArray = [dataArray filteredArrayUsingPredicate:predicate];
Or you can use predicateWithBlock:
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(NSDictionary *evaluatedObject, NSDictionary *bindings) {
return [evaluatedObject[#"profile_picture"] rangeOfString:#"AnonymousUser"].location == NSNotFound;
}];
BTW, if you already have a mutable array, you can also remove entries from it using filterUsingPredicate, using the above predicates:
NSMutableArray *mutableDataArray = [responseDictionary[#"data"] mutableCopy];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"not (profile_picture contains 'AnonymousUser')"];
[mutableDataArray filterUsingPredicate:predicate];
If, on the other hand, you don't want to remove entire dictionaries from the array of dictionaries, but rather want to simply remove the occurrences of profile_picture for which "AnonymousUser" is present, you want to ensure that not only is the array mutable, but so are its constituent dictionaries.
The easiest way of doing this is to specify the NSJSONReadingMutableContainers option when parsing the JSON. Then you can just iterate through the NSMutableDictionary entries, removing the profile_picture entries with a profile_picture with "AnonymousUser" in them:
NSMutableDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:&error];
NSMutableArray *mutableDataArray = responseDictionary[#"data"];
for (NSMutableDictionary *dictionary in mutableDataArray) {
NSString *profilePicture = dictionary[#"profile_picture"];
if ([profilePicture rangeOfString:#"AnonymousUser"].location != NSNotFound) {
[dictionary removeObjectForKey:#"profile_picture"];
}
}
If, however, you can't specify the NSJSONReadingMutableContainers option when you parse the JSON and are stuck with a immutable collection, you need to make a mutable copy of it. Unfortunately, a simple mutableCopy of the array won't make the member dictionaries mutable themselves, but you can use a Core Foundation call to CFPropertyListCreateDeepCopy to make a mutable array with mutable entries, which you can then modify:
NSMutableArray *mutableDataArray = CFBridgingRelease(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFArrayRef)responseDictionary[#"data"], kCFPropertyListMutableContainers));
Then you can use the above for loop, iterating through this array's dictionary entries, removing the offending profile_picture entries.
if [[dictCleanAvatars objectForKey:[keys objectAtIndex:i]] isEqualToString#"anonymousUser"] {
The problem is, suppose [dictCleanAvatars objectForKey:[keys objectAtIndex:i]] is not an NSString? You might want to check for that first.
If the only field you are looking at is profile_picture, I would go with a less generic approach which is much more readable and understandable
This code works for me
- (void)testExample
{
NSDictionary *dictionary = #{ #"data": #[ #{ #"bio": #"blah blah", #"profile_picture": #"some stuff anonymousUser other stuff" },
#{ #"bio": #"some other object", #"profile_picture": #"some other profile picture link" }] };
// dictionary is a mock of the data you provided
NSArray *data = [dictionary objectForKey:#"data"];
for (NSDictionary * avatarDict in data) {
NSMutableDictionary *mdict = [avatarDict mutableCopy];
id ppid = [mdict objectForKey:#"profile_picture"];
if ([ppid isKindOfClass:[NSString class]]) {
NSString *pp = (NSString *)ppid;
if ([pp rangeOfString:#"anonymousUser"].location != NSNotFound) {
[mdict removeObjectForKey:#"profile_picture"];
}
}
NSLog(#"altered dictionary: %#", mdict);
}
}
Output:
2014-08-13 10:53:36.727 test[11981:60b] altered dictionary: {
bio = "blah blah";
}
2014-08-13 10:53:36.728 test[11981:60b] altered dictionary: {
bio = "some other object";
"profile_picture" = "some other profile picture link";
}
I have this for loop that gives me two strings when it is done. However I need to add these two strings into an array. The first string is one and second string is two. So at the end, my NSMutableArray needs to contain both one and two.
How can I perform this correctly?
for (NSDictionary* dict in dictArray) {
NSString *string = ([dict valueForKey:#"string"] == [NSNull null]) ? #"" : [NSString stringWithFormat:#"%#", [dict valueForKey:#"string"]];
}
I also suggest you to simplify your code
NSMutableArray *results = [NSMutableArray array];
for (NSDictionary* dict in dictArray) {
id value = dict[#"string"];
[results addObject: value == [NSNull null] ? #"" : value];
}
First, you need an array to add the string to:
NSMutableArray *resultsArray = [NSMutableArray array];
then you need to add the string to it, in the loop:
[resultArray addObject:string];
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
}
}
I have one NSArray with objects {3, 5, 6} and a NSDictionary with {3, 5} i want to compare those and delete the "6" because its missing from the NSDictionary i'm using the following code
[lists enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
Item *item = (Item *)obj;
NSString *value = [NSString stringWithFormat:#"%#", item.remoteID];
for (NSDictionary *dictionary in responseObject)
{
NSString *idValue = [dictionary objectForKey:#"id"];
if ([value isEqualToString:idValue])
{
NSLog(#"value %#", value);
}
}
}];
NSLog(#"value %#", value);
here i'm getting the correct values but i want to get the missing values in my case "6"
any ideas welcome.
If I understand correctly, you have an array lists and an array responseObject of dictionaries, which contain an id key with the object you want to compare to the array lists.
NSArray *lists = #[#3, #5, #6];
NSArray *responseObject = #[#{#"id":#3},#{#"id":#5}];
Then, you could do something like this to get "the missing values":
NSArray *idValues = [responseObject valueForKey:#"id"];
//Subset of objects in lists that are not present in idValues:
NSMutableArray *result = [NSMutableArray arrayWithArray:lists];
[result removeObjectsInArray:idValues];
There are several ways to go about this.
If you wish to look at it as a filtering task in which you filter the lists array by the id values in the responseObject, then a simple predicate will do:
NSPredicate *responsePred = [NSPredicate predicateWithFormat: #"self IN %#", [responseObject valueForKey: #"id"]];
NSArray *result = [lists filteredArrayUsingPredicate: responsePred];
I am trying to create a String from Array.But, there is condition to how it should be generated, as explained below.
NSArray *array=[NSArray arrayWithObjects:#"Hello",#"World",nil];
[array componentsJoinedByString:#","];
This will output: Hello,World.
But, if first Item is Empty,then is there way to receive the only second one.
Hello , #"" => Hello
#"" , World => World
Hello , World => Hello,World
Another way to do this is to grab a mutable copy of the array and just remove non valid objects. Something like this perhaps:
NSMutableArray *array = [[NSArray arrayWithObjects:#"",#"World",nil] mutableCopy];
[array removeObject:#""]; // Remove empty strings
[array removeObject:[NSNull null]]; // Or nulls maybe
NSLog(#"%#", [array componentsJoinedByString:#","]);
You cannot store nil values in NSArray*, so the answer is "no". You need to iterate the array yourself, keeping track of whether you need to add a comma or not.
NSMutableString *res = [NSMutableString string];
BOOL first = YES;
for(id item in array) {
if (id == [NSNull null]) continue;
// You can optionally check for item to be an empty string here
if (!first) {
[res appendString:#", "];
} else {
first = NO;
}
[res appendFormat:#"%#", item];
}
* nil values in NS collections are represented with NSNull objects.