I have an NSMutableArray with keys UserID and UserName.
I also have an NSDictionary with keys UserID and UserScore.
How do I add the key and values for UserScore from the NSDictionary to the NSMutableArray so that the UserName and UserScore represent the same UserID?
NSMutableArray:
UserID = 123,
UserName = JohnP
NSDictionary:
UserID = 123,
UserScore = 100
Desired output as NSMutableArray:
UserID = 123,
UserName = JohnP,
UserScore = 100
Below is how I retrieve data into the NSMutableArray using Parse and then grab data to a label:
[FBRequestConnection startWithGraphPath:#"/me/friends"
parameters:nil
HTTPMethod:#"GET"
completionHandler:^(
FBRequestConnection *connection,
id result,
NSError *error
) {
FacebookFriends = [result objectForKey:#"data"];
}];
NSString *friendname = [[NSString alloc] initWithFormat:#"%#",[[FacebookFriends objectAtIndex:indexPath.row] objectForKey:#"name"]];
I think you really just wanna use an NSMutableDictionary which is made to store value-key pairs.
You can give your mutable dictionary values from your other dictionary simply by pointing to its key-value (objectForKey).
It looks to me like you want to combine two dictionaries into one:
NSDictionary *dict1 = ...;
NSDictionary *dict2 = ...;
NSMutableDictionary *combined = [NSMutableDictionary new];
NSNumber *userid = dict1[#"UserID"];
NSAssert(userid, #"UserID missing from dict1");
NSAssert([userid isEqualToString:dict2[#"UserID"]], #"Mismatched UserIDs");
NSString *username = dict1[#"UserName"];
NSAssert(username, #"Username missing from dict1");
NSNumber *score = dict2[#"UserScore"];
NSAssert(score, #"Score missing from dict2");
combined[#"UserID"] = userid;
combined[#"UserName"] = username;
combined[#"UserScore"] = score;
However I also suspect you have an array of dictionaries. If so, let me know.
Related
I'm trying to check if NSString 'testing' (47) exists inside of my NSMutableArray 'self.checkfriendData'. I'm using the code below, though after logging my if statement it appears as though it's never executed (even though the statement is true - see console data below, uid = 47, and thus hiding my object should fire?) Any idea as to why this isn't working? Help is much appreciated!
ViewController.m
NSMutableDictionary *viewParams3 = [NSMutableDictionary new];
[viewParams3 setValue:#"accepted_friends" forKey:#"view_name"];
[DIOSView viewGet:viewParams3 success:^(AFHTTPRequestOperation *operation, id responseObject) {
self.checkfriendData = (NSMutableArray *)responseObject;
NSString *testing = #"47";
NSArray *friendorNo = self.checkfriendData;
if ([friendorNo containsObject:testing]) // YES
{
self.addFriend.hidden = YES;
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
Here's what's inside self.checkfriendData:
2017-05-18 19:36:07.266529-0700 This is the friend data check (
{
body = "My name is Britt";
friendphoto = "/sites/default/files/stored/x.jpg";
"node_title" = "Britt";
uid = 47;
}
)
It appears that your NSArray contains NSDictionarys and you are asking if the array contains an NSString. The answer will always be no as the array doesn't directly contain any NSStrings.
If you want to search for the uid of 47 you will have to iterate over the array and check the uid key of each NSDictionary for the value 47.
The code for this would look something like:
for (NSDictionary *dict in friendorNo) {
if ([dict[#"uid"] isEqualToString:testing]) {
self.addFriend.hidden = YES;
}
}
This question already has answers here:
sort NSDictionary values by key alphabetical order
(4 answers)
Closed 6 years ago.
I have a dictionary in which, for a single key(for example key "0") there are a key value pair data.The keys are like name, id,p_id. I want to sort the NSMutableDictionary for the values related to the Key "name". The data in the dictionary is as follows,
0 = {
id = 12;
name = "Accounts ";
"p_id" = 13222071;
};
1 = {
id = 13;
name = "consultant";
"p_id" = 15121211;
};
2 = {
id = 11;
name = "Tania";
"p_id" = 10215921;
};
}
Any help is appreciated!
Please try out the below code:
[yourMutableArray sortUsingComparator: (NSComparator)^(NSDictionary *a, NSDictionary *b) {
NSString *key1 = [a objectForKey: #"name"];
NSString *key2 = [b objectForKey: #"name"];
return [key1 compare: key2];
}];
NSLog(#"Sorted Array By name key : %#", yourMutableArray);
Hope this helps!
NSArray *sortedKeys = [dict.allKeys sortedArrayUsingComparator:^NSComparisonResult(NSDictionary *d1, NSDictionary *d2) {
return [d1[#"name"] compare:d2[#"name"]];
}];
NSArray *objects = [dict objectsForKeys:sortedKeys notFoundMarker:[NSNull null]];
Dictionaries are not sorted, and doesn't resemble any order. What you should do is to getAll the keys first. Then apply a sort method on the keys, then request the objects according to the ordered keys.
E.g:
NSArray *keys = [dictionary allKeys];
NSArray *sortedKeys = <sort the keys according to your preferred method>
Now you can iterate the Dictionary from the order of the array sortedKeys.
While it has been made abundantly clear that Dictionaries can't be sorted and rightfully so, that does not mean the ends you are aiming for can't be achieved. This code will do that for you:
NSArray *arrayOfDicts = dic.allValues; //Now we got all the values. Each value itself is a dictionary so what we get here is an array of dictionaries
NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES]; //Create sort descriptor for key name
NSArray *sortingDesc = [NSArray arrayWithObject:nameDescriptor];
NSArray *sortedArray = [arrayOfDicts sortedArrayUsingDescriptors:sortingDesc]; //Get sorted array based on name
NSMutableDictionary *kindaSortedDict = [[NSMutableDictionary alloc] init];
int keyForDict=0;
for(NSDictionary *valDict in sortedArray)
{
[kindaSortedDict setObject:valDict forKey:[NSString stringWithFormat:#"%i",keyForDict]]; //Set values to our new dic which will be kind of sorted as the keys will be assigned to right objects
keyForDict++;
}
//Now you can simply get sorted array of keys from kindaSortedDic and results for them will always be sorted alphabetically. Alternatively you can just skip all that bother and directly use sortedArray
I have added comments in code to help you understand that.
For accessing sorted values I'd do this:
NSArray *sortedKeys = [kindaSortedDict.allKeys sortedArrayUsingDescriptors:
#[[NSSortDescriptor sortDescriptorWithKey:#"intValue"
ascending:YES]]];
for(NSString *key in sortedKeys)
{
NSDictionary *valDict = [kindaSortedDict objectForKey: key];
NSLog(#"Dict is: %# for key: %#",valDict,key);
}
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";
}
How can i assign value of nsmutable array which is inside of nsmutable dictionary into another nsmutable dictionary or NSDictionary?
NSMutableDictionary *readers = [[NSMutableDictionary alloc] init];
[readers setObject:[[NSMutableArray alloc] init] forKey:#"id"];
readers[#"publicAccess"] = #NO;
// Create dictionary of parameters to be passed with the request
NSDictionary *data = #{
// #"reader_ids": [NSString stringWithFormat:#"%#",[readers[#"id"]componentsJoinedByString:#","]],
};
NSDictionary *data = #{
#"reader_ids": // i need here values of "id" as string which is separated by comma since **reader_ids** is string property and id is MSMutable Array which contains datas.
I need to get value of both id and publicAccess and assign into another NSDictionary.
Try this
NSMutableArray *mArray = readers[#"id"];
BOOL publicAccess = readers[#"publicAccess"];
NSNumber *num = [NSNumber numberWithBool: publicAccess];
NSString * result = [mArray componentsJoinedByString:#","]
NSDictionary * data = #{#"readers_ids" :result,#"publicAccess" : num};
I am stuck on a issue that I am having with core data, Once my app load the core data database gets create. I have a user entity that gets populated via the submit button on the login viewController if the credentials are correct. In the next View I take the return data from the login viewController and submit it to another URL. This gives me JSON return data which gets stored in the database as well.
I have attached my data model and everything work fine except the user entity, I cannot for the life of me to get the right user to go with the data inside the connections.
These are my users
Each user has two records the below is what's getting stored, instead of all all 1's in the user column there should be two 1's and two 2's.
Here is my code that I am using to store the data
User *username = [User MR_findFirstByAttribute:#"username" withValue:currentUser];
NSDictionary *parameters = #{#"DeviceKey": username.guid};
[_operationManager POST:#"GetPrivateRssFeeds" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
//I'm calling all the users with this piece
NSArray *elements = [User MR_findAll];
id attributes = [elements valueForKey:#"username"];
NSLog(#"user: %#",attributes);
username.sessionKey =[[operation.responseObject objectForKey:#"Data"]objectForKey:#"sessionId"];
id connections = [[operation.responseObject objectForKey:#"Data"]objectForKey:#"connections"];
id connection;
NSMutableArray *connectionArray = [NSMutableArray array];
for(connection in connections)
{
//Get the JSON values
NSString *contentSystemID = [connection objectForKey:#"contentSystemId"];
NSString *contentSystemName = [connection objectForKey:#"name"];
NSString *logoUrl = [connection objectForKey:#"logo"];
NSNumber *unreadCount = [connection objectForKey:#"unread_count"];
FCConnection *connectionEntity = [FCConnection MR_createEntity];
connectionEntity.contentSystemID = contentSystemID;
connectionEntity.contentSystemName = contentSystemName;
connectionEntity.logoUrl = logoUrl;
connectionEntity.unreadCount = unreadCount;
// [user addConnections:connection];
[connectionArray addObject:connection];
id categories = [connection objectForKey:#"categories"];
NSMutableArray *categoryArray = [NSMutableArray array];
for (id cat in categories)
{
NSString *title = [cat valueForKey:#"name"];
NSNumber *unreadCount = [cat valueForKey:#"unread_count"];
FCCategory *category = [FCCategory MR_createEntity];
category.title = title;
category.unreadCount = unreadCount;
id items = [cat objectForKey:#"items"];
NSMutableArray *itemArray = [NSMutableArray array];
for (id item in items)
{
NSNumber *isRead = [item valueForKey:#"unread"];
NSString *title = [item valueForKey:#"title"];
NSString *link = [item valueForKey:#"link"];
NSString *systemID = [item valueForKey:#"itemId"];
// BaseTopic *baseEntity = [A MR_createEntity];
// baseEntity.title = title;
Article *article = [Article MR_createEntity];
article.link = link;
article.systemID = systemID;
article.isRead = isRead;
[article setValue:title forKey:#"title"];
article.category = category;
[itemArray addObject:article];
NSLog(#"item %#",itemArray);
}
[category addArticles:[NSSet setWithArray:itemArray]]; // mapping the items to category
category.connection = connectionEntity;
[categoryArray addObject:category];
}
connectionEntity.user = username;
[connectionEntity addCategories:[NSSet setWithArray:categoryArray]]; // mapping the items to connection entity
How can I map the user to the connection?
You are setting the same user entity (i.e., username) for all the connections you are enumerating in that loop (for(connection in connections)). Hence why, It's all set to 1. Set the user entity properly based on your logic.