ios sort a mutable dictionary order [duplicate] - ios

This question already has answers here:
NSDictionary with ordered keys
(9 answers)
Closed 8 years ago.
I saw many examples on SO but I'm not sure if it applies to this situation. Everywhere it says NSMutableDictionries are not guaranteed an order...but I'm getting my data from the server...so my NSMuteDic looks like this:
{
joe = (
{
fromName = joe;
id = 25;
theMessage = "this is going to be a really big message...";
timeAdded = "2014-04-07 21:08:12";
toName = "me";
},
{
fromName = joe;
id = 10;
theMessage = "why???";
timeAdded = "2014-04-05 20:10:04";
toName = "me";
}
);
bob = (
{
fromName = "me";
id = 24;
theMessage = "blah blah";
timeAdded = "2014-04-06 21:15:06";
toName = bob;
},
{
fromName = bob;
id = 22;
theMessage = message;
timeAdded = "2014-04-06 20:11:57";
toName = "me";
}
);
//more entries here
}
What I want to do is change the order...put bob first and joe second. Is this really impossible to do? I saw many very complex solutions...there's no easy way to do this with just a for loop?
cellForRowAtIndexPath:
NSMutableArray *temp = [myDict objectForKey:keys[indexPath.row]];
cell.Message.text = [[reverse lastObject] valueForKey:#"theMessage"];
cell.dateTime.text = [[reverse lastObject] valueForKey:#"timeAdded"];
return cell;
This is how I'm using it...and when a row is selected I pass the array to the next view controller. The reason why I want to reorder is if a new message will be inserted in the pushed view controller, I want that dictionary to be first in the list so the root view controller can be reordered.
NSArray *keys = [myDict allKeys];
[myDict removeObjectForKey:to];
NSMutableDictionary *temp = [NSMutableDictionary dictionaryWithCapacity:[myDict.count];
temp = myDict;
[myDict removeAllObjects];
[myDict setObject:currentDict forKey:to];
for (int i=0; i<temp.count; i++) {
[myDict setObject:[temp valueForKey:keys[i]] forKey:keys[i]];
}
That's not working because it looks like since myDict is a NSObject, temp gets changed every time myDict changes...from the looks of it the logic should work but it isn't...

NSMutableDictionary is not ordered. There is nothing you can do to guarantee the order of keys because NSDictionary makes no attempt to preserve any particular ordering. To go over a dictionary in a particular order, you have to make an array of the keys that is in the order you want, then iterate that and fetch the corresponding values.

// Get the keys
NSArray *keys = [myDict allKeys];
// Sort the keys
NSArray *sortedArray = [NSArray arrayWithArray:[keys sortedArrayUsingComparator:^(NSString* a, NSString* b) {
return [a compare:b];
}]];
// Iterate the dictionary
for (NSUInteger n = 0 ; < [sortedArray count]; n++) {
id value = [myDict objectForKey:[sortedArray objectAtIndex:n]];
}

Related

Group element in NSMutableArray which contains object

I have an NSMutableArray that contains an object of a class model in each position like this.
The class model contains 2 types of information, which we will call id and name.
So, in every location of my NSMutableArray I have an object that contains 2 information.
Then, in the first position of my NSMutableArray I have
{
id = 1;
name = "Dan"; //this is the first object in NSMutableArray
}
In the second position of NSMutableArray, I have:
{
id = 1;
name = "Luca";
}
In the third position
{
id = 2;
name = "Tom";
}
and so on..
Ok, my goal is to make the union of identical IDs between the various objects within the SNMutableArray but it's too difficult!
For example, if I have:
{
id = 1;
name = "Tom";
}
{
id = 1;
name = "Luca";
}
{
id = 2;
name = "Steve";
}
{
id = 2;
name = "Jhon";
}
{
id = 3;
name = "Andrew";
}
The goal is:
{
id = 1;
name = "Tom";
name = "Luca";
}
{
id = 2;
name = "Steve";
name = "Jhon";
}
{
id = 3;
name = "Andrew";
}
Any ideas? would like to use this in the cellForRowAtIndexPath method and I tried to write this: (cm is my class model and myArray is the NSMutableArray which contains an object of cm class)
ClassModel *cm = [myArray objectAtIndex:indexPath.row];
NSMutableArray * resultArray = [NSMutableArray new];
NSArray * groups = [array valueForKeyPath:cm.ID];
for (NSString * groupId in groups)
{
     NSMutableDictionary * entry = [NSMutableDictionary new];
     [insert setObject: groupId forKey: # "groupId"];
     NSArray * groupNames = [array filteredArrayUsingPredicate: [NSPredicate predicateWithFormat: # "groupId =% #", groupId]];
     for (int i = 0; i <groupNames.count; i ++)
     {
         NSString * name = [[groupNames objectAtIndex: i] objectForKey: # "name"];
         [entry setObject: name forKey: [NSS string stringWithFormat: # "name% d", i + 1]];
     }
     [resultArray addObject: entry];
}
NSLog (# "% #", resultArray);
But this does not work..maybe because each element in my array is an object?? .. Help!
You have the right basic idea, but you shouldn't try and do this in cellForRowAt. Rather, you need to create a new array that has the data in the required structure and use that array as the source for your tableview. You will also need to create a new class to put in the array; one that has an id and an NSMutableArray for the names (I won't show this but I will call it GroupClassModel)
Use something like:
NSMutableDictionary *groups = [NSMutableDictionary new]
for (ClassModel *cm in array) {
GroupClassModel *gcm = groups[cm.id];
if (gcm == nil) {
gcm = [GroupClassModel new];
gcm.id = cm.id
groups[cm.id] = gcm
}
[gcm.names addObject:cm.name];
}
NSArray *groupedName = [groups allValues];
// Finally, sort groupedName by id if that is required.

How to retrieve NSStrings stored in multiple NSArrays inside of an NSArray

I'm building an "invite friends" feature.
It's already working I just have one issue I'm wrestling with.
I'm retrieving my contact list, and every time I select a contact I'm adding them to a NSMutableArray which I'm calling "selectedUser".
So each item in the NSMutableArray at this point are "Dictionaries" and some of the values are "Dictionaries" as well. Especially the "phones" key I'm trying to access and retrieve the value key.
What I'm trying to accomplish is to only retrieve the "phone numbers" in strings stored them inside a NSArray that I can then past to [messageController setRecipients:recipents]; recipents being the array of only NSStrings of phone numbers.
This is my code so far, and what I'm getting is a NSArray with multiple NSArrays in it were each array only has one string being the phone number.
NSArray *titles = [self.selectedUsers valueForKey:#"phones"];
NSArray *value = [titles valueForKey:#"value"];
NSLog(#"Output the value: %#", value);
NSArray *recipents = value;
This is what I get in the log
2016-01-04 12:27:59.721 InviteFriends[4038:1249174] (
(
"(305) 731-7353"
),
(
"(786) 306-2831"
),
(
"(305) 333-3297"
)
)
This is the log of the dictionary itself
{
birthday = "";
company = "";
createdAt = "2015-09-06 16:14:18 +0000";
department = "";
emails = (
);
firstName = "Lola";
firstNamePhonetic = "";
id = 699;
jobTitle = "";
lastName = "";
lastNamePhonetic = "";
middleName = "";
nickName = "";
note = "";
phones = (
{
label = Home;
value = "(305) 503-3957";
}
);
prefix = "";
suffix = "";
updatedAt = "2015-09-23 23:31:25 +0000";
}
)
Thanks
If I am understanding this correctly, on the line where you write
NSArray *value = [titles valueForKey:#"value"];,
You are trying to index the NSArray full of dictionaries using the index "value", which doesn't make sense. You should instead loop through your titles array, pull out the value from each dictionary element, and then append that element to your recipents array.
Here is some sample code that should do what I think you want.
NSArray *titles = [self.selectedUsers valueForKey:#"phones"];
NSMutableArray *recipients = [[NSMutableArray alloc] init];
for (NSDictionary* dict in titles) {
NSString* value = [dict objectForKey:#"value"];
[recipients addObject:value];
}
NSLog(#"Phone Numbers: %#",recipients);
Here is the solution I came up with.
First run a for loop to grab the first key. Then nest another for loop to grab the second key.
NSArray *values = self.selectedUsers;
NSMutableArray *recipients = [[NSMutableArray alloc] init];
NSArray *values = self.selectedUsers;
NSMutableArray *recipients = [[NSMutableArray alloc] init];
for (NSDictionary* dict in values) {
// Grabs phones key
NSDictionary *titles = [dict objectForKey:#"phones"];
for (NSDictionary* dict2 in titles) {
// Grabs the "value" key
NSString* value = [dict2 objectForKey:#"value"];
[recipients addObject:value];
}
}

How to replace the NSDictionary value from another value in Objective C? [duplicate]

This question already has answers here:
Replace a value in NSDictionary in iPhone
(5 answers)
Closed 7 years ago.
I have a NSMutableArray below like this
(
{
Realimg = "<UIImage: 0x13951b130>, {800, 600}";
"bid_accepted" = 1;
"bid_amount" = 100;
"bid_amount_num" = 100;
"bid_cur_name" = USD;
"bid_cur_symb" = $;
"bid_currencycode" = 4;
"bid_date" = "05 Nov 2015";
"bid_msg" = testing;
"bid_user_id" = 2;
"nego_id" = 612;
"pas_count" = 5;
"ride_address" = "Sample Address";
"ride_cover_img" = "uploadfiles/UploadUserImages/2/mobile/21426739600s-end-horton-plains.jpg";
"ride_id" = 149;
"ride_name" = "Ride to the World's End";
"ride_type_id" = 0;
"ride_type_name" = Travel;
"ride_user_fname" = Nik;
"ride_user_id" = 2;
"ride_user_lname" = Mike;
}
)
What I want to do is, replace the "bid_currencycode" = 4; by a different value.I want to replace 4 by 5. How can I do this? Please someone help me.
Thank you
You can use the following code for doing the same:
// Getting the dictionary from your array and making it to a mutable copy
NSMutableDictionary *dict = [yourArray[index] mutableCopy];
// Changing the specified key
[dict setObject:#(5) forKey:#"bid_currencycode"];
// Replacing the current dictionary with modified one
[yourArray replaceObjectAtIndex:index withObject:dict];
Here:
yourArray is a NSMutableArray
index is a valid index (index of object, that you need to change the value)
Refer the below coding
NSMutableDictionary *dict =[[NSMutableDictionary alloc]init];
//your array
dic =[yourArray objectAtIndex:0];
[dict removeObjectForKey:#"bid_currencycode"];
[dict setObject:#“5” forKey:#"bid_currencycode"];
[yourArray replaceObjectAtIndex:0 withObject:dict];
0 is (yourArray index number) You can change according your array index number

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.

How to iterate & retrieve values from NSArray of NSArrays of NSDictionaries

I'm stumpped on how iterate and get values for an Array of Arrays of NSDictionaries (different classes/entities). Here's what I'm currently doing:
1) Constructing two separate arrays of NSDictionaries (different entities)
2) Combining both arrays with:
NSMutableArray *combinedArrayofDicts = [[NSMutableArray alloc] initWithObjects: sizesArrayOfDicts, wishListArrayOfDicts , nil];
3) Then archive combinedArrayofDicts :
NSData *dataToSend = [NSKeyedArchiver archivedDataWithRootObject:combinedArrayofDicts];
4) Transmit over GameKit
[self.session sendDataToAllPiers:dataToSend withDataMode: GKSendDataReliable error:nil];
5) How would I manage traversing thru this array on the receiving end? I want to fetch values by for each class which is key'ed by classname:
Here's how it looks via NSLog (2 Sizes Dicts, and 1 Wishlist Dict)
Printing description of receivedArray:
<__NSArrayM 0xbc65eb0>(
<__NSArrayM 0xbc651f0>(
{
classname = Sizes;
displayOrder = 0;
share = 1;
sizeType = Neck;
value = "13\" or 33 (cm)";
},
{
classname = Sizes;
displayOrder = 0;
share = 1;
sizeType = Sleeve;
value = "34\" or 86 (cm)";
}
)
,
<__NSArrayM 0xbc65e80>(
{
classname = Wishlist;
detail = "";
displayOrder = 0;
imageString = "";
latitude = "30.33216666666667";
link = "http://maps.google.com/maps?q=loc:30.332,-81.41";
longitude = "-81.40949999999999";
name = bass;
share = 1;
store = "";
}
)
)
(lldb)
In my for loop I'm issuing this:
NSString *value = [dict objectForKey:#"classname"];
and get an exception:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM objectForKey:]:
unrecognized selector sent to instance 0xbc651f0'
Is this frowned upon as far as mixing object types in arrays of arrays?
#Will guided me to the answer with the right construct.. Here's the final answer:
NSArray *receivedArray;
if(receivedArray.count>0){
NSArray *combinedArrayofDicts = [receivedArray objectAtIndex:0];
if(combinedArrayofDicts.count>=2){
NSArray *sizesArray = [receivedArray objectAtIndex:0]; // Reference original received array
for(NSDictionary *sizeDict in sizesArray){
NSLog(#"%#",sizeDict);
}
NSArray *wishListArray = [receivedArray objectAtIndex:1]; // Reference original received array
for(NSDictionary *wishDict in wishListArray){
NSLog(#"%#",wishDict);
}
}
}
for fetching the required dictionaries use the following code,
Assume receivedArray as the array receive from Game center
NSArray *receivedArray;
if(receivedArray.count>0){
NSArray *combinedArrayofDicts = [receivedArray objectAtIndex:0];
if(combinedArrayofDicts.count>=2){
NSArray *sizesArray = [combinedArrayofDicts objectAtIndex:0];
for(NSDictionary *sizeDict in sizesArray){
NSLog(#"%#",sizeDict);
}
NSArray *wishListArray = [combinedArrayofDicts objectAtIndex:1];
for(NSDictionary *wishDict in wishListArray){
NSLog(#"%#",wishDict);
}
}
}
how iterate and get values for an Array of Arrays of NSDictionaries
As you said you have array of array of dictionaries, your current code will not retrive value of class name.
Your return values are in NSArray not in NSDictionary
So you need to do something like,
NSString *value = [returnArray[0][0] objectForKey:#"classname"];
You can iterate and get values like,
for (int i = 0; i < [returnArray count]; i++) {
for (int j = 0; j < [returnArray[i] count]; j++) {
NSDictionary *dict = (NSDictionary*)returnArray[i][j];
NSLog(#"%# ...",[dict objectForKey:#"classname"]);
}
}
Perhaps you can try:
NSString *value = [NSString stringWithFormat:#"%#",[dict objectForKey:#"classname"]];
By the looks of your output, I don't think "Sizes" is a string.

Resources