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

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.

Related

Objective-C: Remove duplicates efficiently from large data structures

I have an object containing an array of NSNumbers (indexes) and an array of NSDictionaries (indexesTitles) corresponding to indexes, containing some info.
I have to call a method for each object.index and associate object.indexTitles to the returning results, saving them into a single array.
At the end of it, I want to remove indexes duplicates, preserving the associated indextTitles in an efficient way, because I'm working with large arrays.
NSMutableArray *resultArray = [NSMutableArray array];
NSMutableArray *titlesArray = [NSMutableArray array];
for(NSNumber *index in object.indexes)
{
NSArray *resultsIndexArray = [self methodThatReturnsAnArray];
NSString *indexTitleDictionary = [object.indexesTitles objectAtIndex:i];
for(NSNumber *resultId in resultsIndexArray)
{
[titlesArray addObject:indexDictionary];
[resultArray addObject:resultId];
}
i++;
}
[fullResultsArray addObject:titlesArray];
[fullResultsArray addObject:resultArray];
I've found that the most efficient way to remove duplicates is using an
NSOrderedSet like this:
NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:resultArray];
resultArray = [orderedSet.array mutableCopy];
How can I remove the corresponding entries in titlesArray? how can I preserve the association?
I've also tried to use a NSDictionary like {resultId, titleDictionary} and storing them into an array, but I haven't found a efficient way to remove dictionaries with the same result, they are all too slow.
Any suggestion?
It is not completely clear to me what your problem is, maybe this will help:
A good way to remove duplicates is not to add them in the first place, replace:
for(NSNumber *resultId in resultsIndexArray)
{
[titlesArray addObject:indexDictionary];
[resultArray addObject:resultId];
}
with:
for(NSNumber *resultId in resultsIndexArray)
{
// only add if resultId not already in resultArray
if( ![resultArray containsObject:resultId] )
{
[titlesArray addObject:indexDictionary];
[resultArray addObject:resultId];
}
}
The containsObject: call requires a linear search, if your data set is large you might wish to change resultArray to an NSMutableSet and titlesArray to an NSMutableDictionary mapping from resultId to indexDictionary values.
HTH

NSMutableDictionary Removes same values from different array

Hi i am using the following code to remove objects from NSMutableDictionary, both dictionaries contains same array values, if i remove a value from D1 the same value get removed from D2 Automatically.
Help me out how to solve this,
NSMutableDictionary *D1=[[NSMutableDictionary alloc]init];
NSMutableDictionary *D2=[[NSMutableDictionary alloc]init];
NSMutableArray *arr_objs = [[NSMutableArray alloc]initWithObjects:#"ss",#"nn", nil];
[D1 setObject:arr_objs forKey:#"Keys"];
[D2 setObject:arr_objs forKey:#"Keys"];
[[D1 objectForKey:#"Keys"]removeObject:#"nn"];
arr_objs is the same array in two dictionaries. This
NSMutableArray *arr_objs = [[NSMutableArray alloc]initWithObjects:#"ss",#"nn", nil];
NSMutableArray *arr_objsCopy = [arr_objs mutableCopy];
[D1 setObject:arr_objs forKey:#"Keys"];
[D2 setObject:arr_objsCopy forKey:#"Keys"];
should give you what you're looking for. Rather than storing the same array in two dictionaries, this example creates two identical arrays that can later be modified without affecting each other.

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];
}
}

Remove (not exact) duplicates of NSDictionaries from array

I have an NSMutableArray of many NSDictionaries that contain keys like "Title". In some cases there are duplicates of dictionaries with the same "Title" but differences in the other keys.
How can I remove the dictionaries that have the same "Title" key and leave only one in the array?
Thanks
Sort the array using NSSortDescriptor on the key path 'title'. Next, loop over the array and build a new array:
NSString *lastTitle = nil;
NSMutableArray *result = [NSMutableArray array];
for (NSDictionary *d in array) {
NSString *testTitle = [d objectForKey:#"title"];
if (![testTitle isEqualToString:lastTitle]) {
[result addObject:d];
lastTitle = testTitle;
}
}
Now result contains your filtered list.
It's important to sort the array first for this algorithm to work.

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