How would I use an NSMutableArray with a NSMutableDictionary - ios

I have an NSMutableDictionary of websites
[dictionaryOfSites setObject:#"http://www.example.com" forKey:#"Example.com"];
[dictionaryOfSites setObject:#"http://www.site1.com" forKey:#"Site1"];
[dictionaryOfSites setObject:#"http://www.apple.com" forKey:#"Apple"];
I know you can't sort a dictionary. But I've read that other people have used an NSMutableArray as the key and the array can be sorted.
So if I setup a new array
[[arrayKey alloc] initWithObjects:#"Example.com", #"Site1", #"Apple", nil];
I would then modify my first snippet to
[dictionaryOfSites setObject:#"http://www.example.com" forKey:[arrayForKey objectAtIndex:0]];
[dictionaryOfSites setObject:#"http://www.site1.com" forKey:[arrayForKey objectAtIndex:1]];
[dictionaryOfSites setObject:#"http://www.apple.com" forKey:[arrayForKey objectAtIndex:2]];
In this simple problem, I had 3 sites so I "hard" coded it. How would I do the same thing if my list of sites was 100? How would the order of the sites be maintained?
If I sort my array
[arrayKey sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
Wouldn't index 2 become index 0? If it becomes index 0 then you can see the dictionaryOfSites has the wrong label with the URL.

So you can use a custom class (as I mentioned above in my comment), or better yet use an NSDictionary to store the values as MarkM suggested.
EDIT: "i don't have to maintain a dictionary. its a new app from the ground up."
Since you don't need to start with one big dictionary like you posted, it would be better to just store individual dictionary objects for each site in an array and not have to worry about the conversion.
// Setup the initial array
NSMutableArray *arrayOfSites = [NSMutableArray new];
[arrayOfSites addObject:#{#"Name" : #"Example.com",
#"URL" : #"http://www.example.com"}];
[arrayOfSites addObject:#{#"Name" : #"Site1",
#"URL" : #"http://www.site1.com"}];
[arrayOfSites addObject:#{#"Name" : #"Apple",
#"URL" : #"http://www.apple.com"}];
// At this point, arrayOfSites contains a dictionary object for each site.
// Each dictionary contains two keys: Name and URL with the appropriate objects.
// Now we just need to sort the array by the Name key in the dictionaries:
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"Name" ascending:YES];
[arrayOfSites sortUsingDescriptors:[NSArray arrayWithObjects:descriptor, nil]];
NSLog(#"%#", arrayOfSites);
Results:
2013-05-07 18:19:08.386 Testing App[75712:11f03] (
{
Name = Apple;
URL = "http://www.apple.com";
},
{
Name = "Example.com";
URL = "http://www.example.com";
},
{
Name = Site1;
URL = "http://www.site1.com";
} )
To access the data, you would use:
NSString *name = [[arrayOfSites objectAtIndex:indexPath.row] objectForKey:#"Name"];
Note that arrayOfSites should be a declared property of your class so that you can access it from different methods.

What you need to do is store your NSDictionary objects in the array and then access a value from that array to do the sorting if you wish. You don't actually store a new string for the sorting. You just check the value of a certain key in the dictionary at the index in the array.
Here is a good source for sorting an array of dictionaries

Related

Objective-c NSDictionary to NSMutableArray in certain order

So I have this NSDictionary like so:
NSDictionary *productionSchedule = [[[NSMutableDictionary alloc]initWithDictionary:[[areaData GetProductionScheduleData:communityDesc] objectForKey:#"Root"]] autorelease];
The data for the NSDictionary is coming from an API and due to the fact that NSDictionary does not do ordering, the order of the data in API is different in the NSDictionary, so now I am trying to put the keys of the NSDictionary into an NSMutableArray to handle the ordering. In my NSDictionary I have a value called SortOrder and I am trying to put the data in NSDictionary into NSMutableArray based on this value SortOrder (I have about 389 items and the SortOrder goes from 0 - 389) How would I do this?
I have this screenshot that will show you what my data is like:
What I am trying to do is put the key 'V3C0183' but as the 82nd item (there will be 81 items before this)
I am assuming I will have to do a foreach loop like so:
NSMutableArray *prodSchedSortedKeys
for(int i = 0;i<[productionSchedule count];i++)
{
[prodSchedSortedKeys addObject: ? ];
}
I just dont know what the next step would be to add an object based off the sort order....please help.
NSDictionary *dic = //your dictionary;
NSArray<NSDictionary *> *values = dic.allValues;
[values sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
return [obj1[#"SortOrder"] integerValue] > [obj2[#"SortOrder"] integerValue];
}];
Now the dic is ordered.
But this is not the best solution of this problem. Server's data should be ordered instead, that the key like "VC31083" should in the key-value pairs too.
Edit1: sortedArrayUsingComparator: is used for normal sort of array, the performance isn't very well if the content is too large. Especially in this compare, it do addition actions: get value from dictionary, transform NSString to int, and then compare. You can Log to see how much time it spend on this sort with your data.
NSMutableDictionary/NSDictionary can't do that. Take a look at e.g. Matt Gallaghers OrderedDictionary.
Also take a look at this answer:
Getting NSDictionary keys sorted by their respective values

How do i get unique contents from my NSMutableArray?

I have a UITableView and am displaying contents from my NSMutableArray. Following is array format
(
{
Name = "ANS";
VersionNo = 6;
},
{
Name = "O-Hydro";
Version = 6;
},
{
Name = "ANS";
Version = 6;
},
{
Name = "ANTIChorosAnticholinergic";
Version = 6;
}
)
From this I need to display only unique "Name" (like in this I can see 2 "ANS" I need only one).
How can I do this in iOS?
I tried following but its not working
uniqueArray= [[NSMutableSet setWithArray: groupDetails] allObjects];
but in this way I can do only for NSArray not NSMutableArray.
Pls help me
You can use following line of code to convert your NSArray to NSMutableArray,
NSArray *uniqueArray= [[NSMutableSet setWithArray:groupDetails] allObjects];
NSMutableArray *myMutableArray = [[NSMutableArray alloc] initWithArray:uniqueArray];
You could simply add mutableCopy.
But wait, before you do it. Arrays and sets have two differences:
Arrays can contain duplicates, sets cannot.
Arrays are ordered, sets are not.
So doing what you are doing, you lose the duplicates (intentionally), but the order, too (probably not intentionally).
I do not know, whether this is important for you, but for other readers it might be. So it is the better approach to do that with NSOrderedSet instead of NSSet:
NSOrderedSet *uniqueList = [NSOrderedSet orderedSetWithArray:array];
In many cases an ordered set is exactly what you want. (Probably it has been from the very beginning and the usage of NSArray was wrong. But sometimes you get an array.) If you really want an array at the end of the day, you can reconvert it:
array = [uniqueList.array mutableCopy];
If you just want an array of unique name values, you can use #distinctUnionOfObjects with valueForKeyPath -
NSArray *uniqueArray=[groupDetails valueForKeyPath:#"#distinctUnionOfObjects.name"];
But if you want the array to contain the dictionaries that correspond to the unique names then you need to do a little more work -
NSMutableArray *uniqueArray=[NSMutableArray new];
NSMutableSet *nameSet=[NSMutableSet new];
for (NSDictionary *dict in groupDetails) {
NSString *name=dict[#"name"];
if (![nameSet containsObject:name]) {
[uniqueArray addObject:dict];
[nameSet addObject:name];
}
}

How to populate an array with dictionaries containing certain key/values

I'm working with a plist file at the moment but intend to switch over to json when the backend is finally built. So for the moment my plist is an array that contains a bunch of dictionaries.
I'd like to use this information to create a new array containing only the dictionaries with certain values.
For example. My plist contains a bunch of locations like so:
key: location value:example place name here
key: type value:indoor
I want to build an array containing only those with "indoor" set as the type value.
And then perhaps a second one containing all "outdoor" locations.
What's the best way to go about doing this, or perhaps I can be directed to a tutorial of some sort.
Thanks.
Simply loop through your array and add the qualifying dictionaries to a new array.
NSMutableArray *arrayIndoor = [NSMutableArray array];
NSMutableArray *arrayOutdoor = [NSMutableArray array];
NSString *type;
for (NSDictionary *dict in arrayPList) {
type = [dict objectForKey:#"type"];
if ([type isEqualToString:#"indoor"])
[arrayIndoor addObject:dict];
else if ([type isEqualToString:#"indoor"])
[arrayOutdoor addObject:dict];
}
All you are really needing to do is sort the array into two arrays. There isn't a direct method that I have seen that will do this for you. My suggestion would be to use a fast enumeration over the array and conditionally break it into two new arrays.
NSMutableArray *locations = [[NSMutableArray alloc] init];
NSMutableArray *type = [[NSMutableArray alloc] init];
for (NSDictionary *dict in MyPlistArray) {
if ([dict valueForKey:#"locationKey"]) {
[locations addObject:dict];
} else if ([dict valueForKey:#"typeKey"]) {
[type addObject:dict];
}
}
You might need to use a different method for determining which key to put in each array, but you get the general idea.
Also I'm assuming that you would want the arrays of dictionaries to persist after, so you can just set those up as properties instead of local variables.

sort NSDictionary based on single object key

I would like some help sorting an NSArray of NSDictionary values based on each objects ISV key.
This is the code I have so far for creating my array objects so you have a better idea of what I am trying to do.
NSArray *combinedKeysArray = [NSArray arrayWithObjects:#"HASM", #"ISL", #"ISV", nil];
valuesCombinedMutableArray = [NSMutableArray arrayWithObjects:[dict objectForKey:#"HASM"],
[dict objectForKey:#"ISL"],
[dict objectForKey:#"ISV"],
nil];
combinedDictionary = [NSDictionary dictionaryWithObjects:valuesCombinedMutableArray
forKeys:combinedKeysArray];
[unSortedrray addObject:combinedDictionary];
// how do I then sort unSortedArray by the string values in each object ISV key?
any help would be greatly appreciated.
This can solve your problem
How to sort an NSMutableArray with custom objects in it?
https://stackoverflow.com/a/805589/1294448
You can use NSSortDescriptor to sort NSArays
Then in NSArray you have a method called sortedArrayUsingDescriptors
Or NSComparisonResult ca also be helpful some time http://developer.apple.com/DOCUMENTATION/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html#//apple_ref/doc/uid/20000138-BABCEEJD
you won't be able to sort unSortedArray because it will only have one element in it (ie in your last line of code you are adding a single object by addObject).
That said, you cannot sort the dictionary either.. b/c dictionaries are unsorted by definition.
you can iterate over the keys of the dictionary in a specific order though, you can sort an array containing the keys of the dictionary.
NSArray *keys = [theDictionary allKeys];
NSArray *sortedKeys = [keys sortedArrayUsingSelector:#selector(compareMethod:)];
You can use -sortedArrayUsingComparator: to sort any way you need.
[unSortedrray sortedArrayUsingComparator:^NSComparisonResult(NSDictionary *dict1, NSDictionary *dict2) {
return [[dict1 objectForKey:#"ISV"] localizedCompare:[dict2 objectForKey:#"ISV"]];
}];

What's the standard convention for creating a new NSArray from an existing NSArray?

Let's say I have an NSArray of NSDictionaries that is 10 elements long. I want to create a second NSArray with the values for a single key on each dictionary. The best way I can figure to do this is:
NSMutableArray *nameArray = [[NSMutableArray alloc] initWithCapacity:[array count]];
for (NSDictionary *p in array) {
[nameArray addObject:[p objectForKey:#"name"]];
}
self.my_new_array = array;
[array release];
[nameArray release];
}
But in theory, I should be able to get away with not using a mutable array and using a counter in conjunction with [nameArray addObjectAtIndex:count], because the new list should be exactly as long as the old list. Please note that I am NOT trying to filter for a subset of the original array, but make a new array with exactly the same number of elements, just with values dredged up from the some arbitrary attribute of each element in the array.
In python one could solve this problem like this:
new_list = [p['name'] for p in old_list]
or if you were a masochist, like this:
new_list = map(lambda p: p['name'], old_list)
Having to be slightly more explicit in objective-c makes me wonder if there is an accepted common way of handling these situations.
In this particular case Cocoa is not outdone in succinctness :)
NSArray *newArray = [array valueForKey:#"name"];
From the NSArray documentation:
valueForKey:
Returns an array containing the
results of invoking valueForKey: using
key on each of the receiver's objects.

Resources