How to find two NSArray has common NSDictionary - ios

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
}

Related

Search NSArray of NSDictionary. How to find using NSPredicate?

I have an NSArray. It has one or more NSDictionary in each index. Based on the search input, I want to check whether it contain the value in contact_Label inside contact_detail dictionary. It will look like this:
(
{
"contact_detail" = {
"contact_is_in_phone" = 1;
"contact_Label" = "Tyler Globussoft";
"contact_displayname" = "Suzan Arohh";
},
"last_msg_details" = {
.....
};
},
{
}
);
I have tired like this. But not getting the result.
NSArray *contacts = self.dataArray; //your array of NSDictionary objects
NSPredicate *filter = [NSPredicate predicateWithFormat:#"contact_Label = %#",stringValue];
NSArray *filteredContacts = [contacts filteredArrayUsingPredicate:filter];
You can use
NSArray *contacts = self.dataArray; //your array of NSDictionary objects
NSPredicate *filter = [NSPredicate predicateWithFormat:#"contact_detail.contact_Label = %#",stringValue];
NSArray *filteredContacts = [contacts filteredArrayUsingPredicate:filter];
Happy coding...

Create an array of NSSet having values of distinct properties of an object present in another NSArray

I have an array having objects with different properties. I want to create an array of sets which contain objects with same value of a single property of the object.
Suppose this is an array of object which has property a and b
1: {a:10, b:5}, 2: {a:2,b:5}, 3: {a:20,b:5}, 4: {a:5,b:5}, 5: {a:4,b:20}, 6: {a:51,b:20}
I want to create another array of NSSet of objects with distinct values of property b
so the result would be the following Array of 2 NSSet
1: {a:10, b:5}, {a:2,b:5}, {a:20,b:5}, {a:5,b:5}
2: {a:4,b:20}, {a:51,b:20}
How can this be done?
I'd do this by first creating a dictionary of sets where the keys of the dictionary are the unique values of "b".
Note: This is untested code. There could be typos here.
NSArray *objectArray = ... // The array of "SomeObject" with the "a" and "b" values;
NSMutableDictionary *data = [NSMutableDictionary dictionary];
for (SomeObject *object in objectArray) {
id b = object.b;
NSMutableSet *bSet = data[b];
if (!bSet) {
bSet = [NSMutableSet set];
data[b] = bSet;
}
[bSet addObject:object];
}
NSArray *setArray = [data allValues];
setArray will contain your array of sets.
This codes also assumes you have a sane isEqual: and hash implementation on your SomeObject class.
This is how you can do this:
NSArray *data = #[#{#"a":#10, #"b":#5}, #{#"a":#2,#"b":#5}, #{#"a":#4,#"b":#20}, #{#"a":#51,#"b":#20}];
NSSet *bSet = [NSSet setWithArray: [data valueForKey: #"b"]];
NSMutableArray *filteredArray = [[NSMutableArray alloc] initWithCapacity: bSet.count];
for (NSNumber *bValue in bSet) {
NSPredicate *anArrayFilterPredicate = [NSPredicate predicateWithBlock:^BOOL(NSDictionary *aDictionaryData, NSDictionary *bindings) {
if ([aDictionaryData[#"b"] isEqual:bValue]) {
return YES;
}
return NO;
}];
NSArray *uniqueBValueArray = [data filteredArrayUsingPredicate:anArrayFilterPredicate];
[filteredArray addObject:uniqueBValueArray];
}
NSLog(#"filteredArray = %#", filteredArray);
Using Key-Value coding collection operators, we can get the array of distinct values for an object. Then you could easily compute the results you want.
In your case this could be done like this.
NSArray *arrayOfDistinctObjects = [array valueForKeyPath:#"#distinctUnionOfObjects.b"];
NSMutableArray *newSetArray = [NSMutableArray new];
for (id value in arrayOfDistinctObjects) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.b == %#", value];
NSArray *filterArray = [array filteredArrayUsingPredicate:predicate];
NSSet *newSet = [NSSet setWithArray:filterArray];
[newSetArray addObject:newSet];
}
where array is the array of objects on which you wanna operate.
arrayOfDistinctObjects gives you the array of distinct values for b.

Remove object from dictionary if a value is not found in an array

I am trying to manipulate an array of dictionaries based on an array of values.
for example:
arrayOfDicts =
(
{
caption = a;
urlRep = "12";
},
{
caption = b;
urlRep = "34";
},
{
caption = c;
urlRep = "56";
}
)
Array of values:
urlReps = (12,56);
outcome I am trying to achieve:
(
{
caption = a;
urlRep = "12";
},
{
caption = c;
urlRep = "56";
}
)
The code I have now that adds to it based on the array is this:
NSMutableArray *arrayOfDicts;
NSMutableSet *urlReps;
[urlReps minusSet:[NSSet setWithArray:[arrayOfDicts valueForKey:#"urlRep"]]];
// merge new dicts to the original array
for (id urlRep in urlReps)
{
[arrayOfDicts addObject:#{ #"urlRep" : urlRep, #"caption" : #"" }];
}
This adds to my array of dicts if there are more urls in the array but I need to also remove if there are less urls in the array compared to the dict
Try something Like this using NSPredicate to filter the array:
NSArray *arrayOfDicts = .... //your existing data
NSArray *filteredURLParams = #[#"12",#"56"];
NSPredicate *urlPredicate = [NSPredicate predicateWithFormat:#"urlRep IN %#",filteredURLParams];
NSArray *filteredDicts = [arrayOfDicts filteredArrayUsingPredicate:urlPredicate];
Here's some old fashioned, straightforward, and completely untested code :-)
// Your data
NSMutableArray* arrayOfDicts = [...];
NSMutableSet* urlReps = [...];
// Will receive those dictionaries that have a matching urlRep
NSMutableArray* filteredArrayOfDicts = [NSMutableArray arrayWithCapacity:0];
// Initially contains all urlReps, but we will successively
// eliminate those urlReps that we encountered
NSMutableSet* urlRepsNotSeen = [NSMutableSet setWithCapacity:0];
[urlRepsNotSeen addObjects:[urlReps allObjects]];
for (NSDictionary* dict in arrayOfDicts)
{
NSString* urlRep = [dict valueForKey:#"urlRep"];
if ([urlReps containsObject:urlRep])
[
[filteredArrayOfDicts addObject:dict];
// Not sure what happens if urlRepsNotSeen does not contain the
// urlRep (because we eliminated it earlier). If it crashes, add
// this check:
// if ([urlRepsNotSeen containsObject:urlRep])
[urlRepsNotSeen removeObject:urlRep];
}
arrayOfDicts = filteredArrayOfDicts;
for (NSString urlRepNotSeen in urlRepsNotSeen)
{
[arrayOfDicts addObject:#{ #"urlRep" : urlRepNotSeen, #"caption" : #"" }];
}

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

How to sort Array containing that contains NSDictionaries [duplicate]

This question already has answers here:
Sorting NSArray of dictionaries by value of a key in the dictionaries
(11 answers)
Closed 9 years ago.
Suppose I would like to sort array by "firstName" key.
Example
Array = (
{
People1 = {
firstName = #"Jack Adam";
email = #"adam#gmail.com";
};
Address = {
cityCode = #"TH";
};
},
People2 = {
firstName = #"Jack DAm";
email = #"dam#gmail.com";
};
Address = {
city = #"TH";
};
);
user Sort Comparator
NSArray *sortedArray = [unsortedArray sortedArrayUsingComparator:^(NSDictionary *a, NSDictionary *b) {
return [a[#"People"][#"firstname"] compare:b[#"People"][#"firstname"]];
}];
But Your Key is inconsistency ...
I Think that data should be
Array = (
{
People = {
firstName = #"Jack Adam";
email = #"adam#gmail.com";
};
Address = {
cityCode = #"TH";
};
},
People = {
firstName = #"Jack DAm";
email = #"dam#gmail.com";
};
Address = {
city = #"TH";
};
);
Using blocks and modern Objective-C syntax:
NSArray *sortedArray = [unsortedArray sortedArrayUsingComparator:^(NSDictionary *first, NSDictionary *second) {
return [first[#"Person"] compare:second[#"Person"]];
}];
Using NSSortDescriptor:
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"firstName" ascending:YES];
myArray=[stories sortedArrayUsingDescriptors:[NSArray arrayWithObjects:descriptor,nil]];
temp = [stories copy]; //temp is NSMutableArray
myArray is the array you want to sort.
First,you should implement a compare-method for your object.
- (NSComparisonResult)compare:(Person *)otherObject {
return [self.birthDate compare:otherObject.birthDate];
}
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingSelector:#selector(compare:)];
As you replied in a comment, the first dictionary key is "Person1" in all array elements.
Then "Person1.firstName" is the key path that gives the first name of each array
element. This key path can be used in a sort descriptor:
NSArray *array = ... // your array
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"Person1.firstName" ascending:YES];
NSArray *sortedArray = [array sortedArrayUsingDescriptors:#[sort]];

Resources