How to get unique keys in a NSDictionary? - ios

This is the NSDictionary I have:
locations: {
509f3a914d026b589ba3a090 = {
coordinates = {
latitude = "29.76429";
longitude = "-95.3837";
};
country = USA;
id = 509f3a914d026b589ba3a090;
name = Houston;
state = Texas;
};
509f3b3a4d026b589ba3a091 = {
coordinates = {
latitude = "3.138722";
longitude = "101.686849";
};
country = Malaysia;
id = 509f3b3a4d026b589ba3a091;
name = "Kuala Lumpur";
};
509f475b4d026b589ba3a093 = {
coordinates = {
latitude = "32.803468";
longitude = "-96.769879";
};
country = USA;
id = 509f475b4d026b589ba3a093;
name = Dallas;
state = Texas;
};
}
What I am wanting to do is to just get the countries and as you can tell I have two values for "USA". I just want to extrapolate USA and Malaysia. And not USA,Malaysia, USA.
I hope I am making sense

I think the simplest method would be:
[NSSet setWithArray:[[dictionary allValues] valueForKey:#"country"]];
So you:
get the array of all values in the top-level dictionary;
call valueForKey: on that array — which is defined to call valueForKey: on everything in the array in turn and then return an array of the answers, and valueForKey: on a dictionary is the same as objectForKey: if the key in question doesn't being with an '#';
create a set from the resulting array, hence resolving any repetitions.
You could add a call to allObjects on the resulting set if you wanted to end up with an array.

Say you have a dictionary called locations and one of the objects in your dictionary is a country. Also you say just extrapolate I'll assume you want to add it to some array or something. For this problem you could use a set to make sure you aren't entering the same country more then once.
NSMutableSet *set = [NSMutableSet set];
NSMutableArray *array = [NSMutableArray array];
NSString *country = [locations objectForKey:#"country"];
if ([set containsObject:country])
{
[array addObject:country]; // Extrapolating country from dictionary to array
[set addObject:country]; // Addind it to set to check later
}

I would do this way:
NSMutableArray *newArray = [NSMutableArray array];
NSMutableSet *currentCountries = [NSMutableSet set];
for(NSDictionary* dic in [[currentDict objectForKey:#"locations"] allValues])
{
if(![currentCountries containsObject:[dic objectForKey:#"country"])
{
[currentCountries addObject:[dic objectForKey:#"country"]]
[newArray addObject:dic];
}
}

Related

How to find two NSArray has common NSDictionary

I have an NSArray. It has one or more NSDictionary. otherContacts has one dictionary in each index. chatContacts has two dictionary in each index. How can i find both Array has same contact_detail.
NSArray * otherContacts = {
"contact_detail" = {
"contact_Label" = "Test 5 ";
userid = 48;
};
}
NSArray * chatContacts ={
"contact_detail" = {
"contact_Label" = "Test 5 ";
userid = 48;
};
"last_msg_details" = {
"Key_from_me" = 1;
data = " B";
};
}
I have tried like this using NSPredicate. But Its not returning the common data.
NSArray *filtered = [otherContacts filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
return [chatContacts containsObject:evaluatedObject];
}]];
May be you can use NSMutableSet to accomplish that:
Like,
NSMutableSet* set1 = [NSMutableSet setWithArray:array1];
NSMutableSet* set2 = [NSMutableSet setWithArray:array2];
//Find intersect: Which will give common objects
[set1 intersectSet:set2];
//Array with common objects
NSArray* arrCommon = [set1 allObjects];
//Now check common objects count to find if it has common object
if(arrCommon.count>0){
//has common dictionary
}

Compare the unique index value with another array in objective C

There is an array having same objects in single array , i need to compare these array’s index with another array.. Give me a help.
Something like:
NSMutableArray *latArray =
[NSMutableArray arrayWithObjects:#“43.20,#“43.23”,#“43.24”,#“43.20”,nil];
NSMutableArray *lngArray =
[NSMutableArray arrayWithObjects:#“76.90”,#“76.94”,#“76.92”,#“76.90”,nil];
NSMutableArray *imagesArray =
[[NSMutableArray alloc] initWithObjects:#"1.jpg", #"2.jpg”,#“3.jpg”,#“4.jpg”,nil];
resultResult = #"1.jpg", #“4.jpg” // because the index 0 and index 3 same values in both array.
I would wrap your coordinates into location objects and use them as the keys in a dictionary. This would allow to check for duplicate coordinates, like this:
NSMutableDictionary *results = [[NSMutableDictionary alloc] init];
for (int i = 0; i < [imagesArray count]; i++)
{
// Wrap coordinates into a NSValue object
// (CLLocationCoordinate2D is a C-struct that cannot be used as a dictionary key)
// (CLLocation also does not implement required methods to be usable as a dictionary key)
NSValue *loc = [NSValue valueWithMKCoordinate:CLLocationCoordinate2DMake(
((NSNumber)[latArray objectAtIndex:i]).doubleValue,
((double)[lngArray objectAtIndex:i]).doubleValue)];
// 1. If you only want the first occurrence of a specific location, use this:
if ([results objectForKey:loc] == nil)
{
[results setObject:[imagesArray objectAtIndex:i] forKey:loc];
}
// 2. Or, if you want the last occurrence of a specific location, use this:
[results setObject:[imagesArray objectAtIndex:i] forKey:loc];
}
I think you are trying the check for the same objects in an array. If so do the following.
for(int i=0;i<yourarray.count;i++)
{
NSString *yourstring=[yourarray objectatindex:i];
for(int k=0;k<yourarray.count;k++)
{
if(i!=k)
{
NSString *yourstring2=[yourarray objectatindex:k];
if([yourstring isEqualtostring yourstring2])
{
//now you got equal objects. do what ever you want here
}
}
}
}

Merge an array into a dictionary

I am trying to take an array and merge it into an array of dictionaries but unsure as to how to do it.
I have an array of dictionaries that looks like this:
(
{
caption = a;
urlRep = "12";
},
{
caption = b;
urlRep = "34";
},
{
caption = c;
urlRep = "56";
}
)
and given an array like this:
(12,34,56,78)
I want to merge it into my dictionaries to make it look like this:
(
{
caption = a;
urlRep = "12";
},
{
caption = b;
urlRep = "34";
},
{
caption = c;
urlRep = "56";
},
{
caption = "";
urlRep = "78";
}
)
edit:
I need to also consider removing from the array of dicts if the given array does not contain one of the urlReps.
Any help would be greatly appreciated as I've been stuck trying to figure this out for some time.
Here's a simple, efficient and elegant solution using NSSets to handle unique keys:
NSMutableArray *arrayOfDicts; // your input array of dictionaries
NSArray *urlRepArray; // the new array with string elements
// create a set of potentially new keys (urlReps)
NSMutableSet *urlReps = [NSMutableSet setWithArray:urlRepArray];
// remove existing keys from your original array
[urlReps minusSet:[NSSet setWithArray:[arrayOfDicts valueForKey:#"urlRep"]]];
// merge new dicts to the original array
for (id urlRep in urlReps)
[arrayOfDicts addObject:#{ #"urlRep" : urlRep, #"caption" : #"" }];
Easiest way AFAIK, Filter using valueForKeyPath
//Your array of dictionary I created here for debugging purpose.
NSArray *tmpArray = #[ #{#"caption":#"a",#"urlRep":#"12"},
#{#"caption":#"b",#"urlRep":#"34"},
#{#"caption":#"c",#"urlRep":#"56"}];
//This will give you 12,34,56 in your case
NSArray *existingURLRep = [tmpArray valueForKeyPath:#"urlRep"];
NSMutableArray *targetArray = [[NSMutableArray alloc] initWithObjects:#12, #34,#56, #78, nil]; //Assuming you have your array as you said
[targetArray removeObjectsInArray:existingURLRep];
//remove existing items you will have 78 here now loop through
//this targetArray and add it to your array of dictionary.
(void)filterArray{
NSLog(#"Array before filtering = %#",initialArray);
NSLog(#"given Array = %#",givenArray);
NSMutableSet *urlReps = [NSMutableSet setWithArray:givenArray];
// remove existing records
[urlReps minusSet:[NSSet setWithArray:[initialArray valueForKey:#"urlRep"]]];
// adding new objects
for (id obj in urlReps) {
[initialArray addObject:#{#"caption":#"", #"urlRep" : obj}];
}
// removing objects
NSMutableSet *set = [[NSMutableSet alloc] init];
for (id obj in initialArray) {
NSDictionary *dict = (NSDictionary *)obj;
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"self = %#", dict[#"urlRep"]];
NSArray *filteredArray = [givenArray filteredArrayUsingPredicate:predicate];
if(filteredArray.count == 0) {
[set addObject:dict];
}
}
[initialArray removeObjectsInArray:[set allObjects]];
NSLog(#"Array after filtering = %#",initialArray);
}
NSMutableArray *yourArray;//This will be your original array of dictionary.
NSArray *newArray;//This is your new array which you want to add.
for(id obj in newArray) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"urlRep = %#", id];
NSArray *filteredArray = [locationsArray filteredArrayUsingPredicate:predicate];
if(filteredArray.count == 0) {
[yourArray addObject:#{#"caption":#"", #"urlRep" : id}];
}
}
/*
NSArray *inputArray;//(12,34,56,78)- I assumes you are having array which contains strings. If you are having number then modify the code as you needed
NSMutableArray *colloectionArray;// your total collection
NSMutableArray *tobeMerged;
*/
// Extract the dictionary set only to be merged
for (NSString* aNumber in inputArray) {
for (NSDictionary *aItem in colloectionArray) {
NSString *urlRep= [aItem valueForKey:#"urlRep"];
if (![urlRep isEqualToString:aNumber]) {
[tobeMerged addObject:urlRep];
}
}
}
// Add missed items in collection
for (NSString *aNumber in tobeMerged) {
NSMutableDictionary *newset = [[NSMutableDictionary alloc]init];
[newset setObject:#"" forKey:#"caption"];
[newset setObject:aNumber forKey:#"urlRep"];
[colloectionArray addObject:newset];
}

Extracting one property out of a JSON response

I'm horrible at JSON. I don't understand a single thing. My JSON response looks like this:
{
ID = 1;
EDate = "<null>";
SelectedDay = "/Date(-62135596800000)/";
End = "14.09.2013 15:00:00";
Start = "14.09.2013 07:00:00";
SDate = "<null>";
},
{
ID = 1;
EDate = "<null>";
SelectedDay = "/Date(-62135596800000)/";
End = "14.09.2013 16:00:00";
Start = "14.09.2013 07:00:00";
SDate = "<null>";
},
In both NSData and NSDictionary. How can I loop trough, for example, the "End" property of each object, and add them to an array?
Edit:
I log from this code:
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:result.data options:kNilOptions error:&error];
NSLog(#"Response: %#",dict);
and the complete log is:
This JSON seems to be an array of dictionaries. Try with:
NSMutableArray *endValuesArray = [[NSMutableArray alloc] init];
for (NSDictionary *dictionary in JSONArray) {
[endValuesArray addObject:[dictionary valueForKey:#"End"]];
}
Where JSONArray is the array obtained after NSJSONSerialization.
If you really just need an array of the values for a single key in each dictionary then you can use KVC:
NSArray *endValues = [resultsArray valueForKey:#"End"];
-- This is assuming that you do have an array of dictionaries and that your pasted log just doesn't show the full story.
If you need multiple keys / values out of the dictionaries then you're best to iterate over the contents and pick each item. There are various methods of iteration that you can look at using plain loops or blocks.
Use this :
NSMutableArray *endDatesArray = [NSMutableArray new]; // Here this array will store all end dates
for (int i =0; i < [YOUR_JSONARRAY count]; i++) // Here YOUR_JSONARRAY is the response array you are getting
{
NSMutableDictionary *dict= [YOUR_JSONARRAY objectAtIndex:i];
[endDatesArray addObject:[dict objectForKey:#"End"]];
}
Hope it helps you.
Make an NSArray of the JSON Object.
Use a FOR loop up to the count of the array to create an NSDictionary for each array object
Use 'objectForKey:#"End"' to extract the End object. (within the for loop)

Split NSArray into sub-arrays based on NSDictionary key values

We have an app that calls a SOAP web service and retrieves a long list of XML, which the app then parses into an NSArray of NSDictionary objects. The NSArray contains a list of Rental Apartment information, each of which is stored into an NSDictionary.
The entire list may contain 10 different types of Apartments (i.e. 2-room, 3-room), and we need to split the NSArray into smaller NSArrays based on Room-Type, which has the key "roomType" in the NSDictionary objects.
Currently our algorithm is
Use [NSArray valueForKeyPath:#"#distinctUnionofObjects.room-type"]
to obtain a list of unique room-type values.
Loop through the list of unique room-type values
For each unique room-type value, use NSPredicate to retrieve matching items from the Original list
Our code is below (renamed for clarity):
NSArray *arrOriginal = ... ...; // Contains the Parsed XML list
NSMutableArray *marrApartmentsByRoomType = [NSMutableArray arrayWithCapacity:10];
NSMutableArray *arrRoomTypes = [arrOriginal valueForKeyPath:#"distinctUnionOfObjects.roomType"];
for(NSString *strRoomType in arrRoomTypes) {
NSPredicate *predicateRoomType = [NSPredicate predicateWithFormat:#"roomType=%#", strRoomType];
NSArray *arrApartmentsThatMatchRoomType = [arrOriginal filteredArrayUsingPredicate:predicateRoomType]; // TAKES A LONG TIME EACH LOOP-ROUND
[marrApartmentsByRoomType addObject:arrApartmentsThatMatchRoomType];
}
However, step 3 is taking a long time as the original list may contain large amount (>100,000) of items. It seems that NSPredicate goes through the entire list for each key value. Is there a more efficient way of splitting a large NSArray into smaller NSArrays, based on NSDictionary keys?
If the order of your splited Arrays is not important, i have a solution for you:
NSArray *arrOriginal;
NSMutableDictionary *grouped = [[NSMutableDictionary alloc] initWithCapacity:arrOriginal.count];
for (NSDictionary *dict in arrOriginal) {
id key = [dict valueForKey:#"roomType"];
NSMutableArray *tmp = [grouped objectForKey:key];
if (tmp == nil) {
tmp = [[NSMutableArray alloc] init];
[grouped setObject:tmp forKey:key];
}
[tmp addObject:dict];
}
NSMutableArray *marrApartmentsByRoomType = [grouped allValues];
This is quite performant
- (NSDictionary *)groupObjectsInArray:(NSArray *)array byKey:(id <NSCopying> (^)(id item))keyForItemBlock
{
NSMutableDictionary *groupedItems = [NSMutableDictionary new];
for (id item in array) {
id <NSCopying> key = keyForItemBlock(item);
NSParameterAssert(key);
NSMutableArray *arrayForKey = groupedItems[key];
if (arrayForKey == nil) {
arrayForKey = [NSMutableArray new];
groupedItems[key] = arrayForKey;
}
[arrayForKey addObject:item];
}
return groupedItems;
}
Improving #Jonathan answer
Converting array to dictionary
Maintaining the same order as it was in original array
//only to a take unique keys. (key order should be maintained)
NSMutableArray *aMutableArray = [[NSMutableArray alloc]init];
NSMutableDictionary *dictFromArray = [NSMutableDictionary dictionary];
for (NSDictionary *eachDict in arrOriginal) {
//Collecting all unique key in order of initial array
NSString *eachKey = [eachDict objectForKey:#"roomType"];
if (![aMutableArray containsObject:eachKey]) {
[aMutableArray addObject:eachKey];
}
NSMutableArray *tmp = [grouped objectForKey:key];
tmp = [dictFromArray objectForKey:eachKey];
if (!tmp) {
tmp = [NSMutableArray array];
[dictFromArray setObject:tmp forKey:eachKey];
}
[tmp addObject:eachDict];
}
//NSLog(#"dictFromArray %#",dictFromArray);
//NSLog(#"Unique Keys :: %#",aMutableArray);
//Converting from dictionary to array again...
self.finalArray = [[NSMutableArray alloc]init];
for (NSString *uniqueKey in aMutableArray) {
NSDictionary *aUniqueKeyDict = #{#"groupKey":uniqueKey,#"featureValues":[dictFromArray objectForKey:uniqueKey]};
[self.finalArray addObject:aUniqueKeyDict];
}
Hope, It will help when client wants final array in same order as input array.

Resources