compare two arrays and get the common items - iphone

I have two arrays, but they have different lengths. I want to compare these two arrays and put common items to a new array. meanwhile there should not be have duplicate items is the third array.
I really mess up with this, please give me a help.
highly thankful . . .

Something like this?
NSMutableSet* set1 = [NSMutableSet setWithArray:array1];
NSMutableSet* set2 = [NSMutableSet setWithArray:array2];
[set1 intersectSet:set2]; //this will give you only the objects that are in both sets
NSArray* result = [set1 allObjects];
This has the benefit of not looking up the objects in the array, while looping through another array, which has N^2 complexity and may take a while if the arrays are large.
Edit: set2 doesn't have to be mutable, might as well use just
NSSet* set2 = [NSSet setWithArray:array2];

A third approach (besides using sets or the simple loop checking each item with contains) would be to sort both arrays, and then use two indices:
// approach using sets:
NSArray *arrayUsingSets(NSMutableArray *arr1, NSMutableArray *arr2)
{
NSMutableSet *set1 = [NSMutableSet setWithArray: arr1];
NSSet *set2 = [NSSet setWithArray: arr2];
[set1 intersectSet: set2];
return [set1 allObjects];
}
// my approach:
NSArray *arrayUsingComp(NSMutableArray *arr1, NSMutableArray *arr2)
{
NSMutableArray *results = [NSMutableArray arrayWithCapacity: arr1.count + arr2.count];
// Assumes input arrays are sorted. If not, uncomment following two lines.
// [arr1 sortUsingSelector: #selector(compare:)];
// [arr2 sortUsingSelector: #selector(compare:)];
int i = 0;
int j = 0;
while ((i < arr1.count) && (j < arr2.count))
{
switch ([[arr1 objectAtIndex: i] compare: [arr2 objectAtIndex: j]])
{
case NSOrderedSame:
[results addObject: [arr1 objectAtIndex: i]];
i++, j++;
break;
case NSOrderedAscending:
i++;
break;
case NSOrderedDescending:
j++;
break;
}
}
// NOTE: results are sorted too.
// NOTE 2: loop must go "backward".
for (NSInteger k = results.count - 1; k > 0; k--)
if ([[results objectAtIndex: k] isEqual: [results objectAtIndex: k-1]])
[results removeObjectAtIndex: k];
return results;
}
I did some simple profiling, and if I make mutable copies of the arrays passed in, and sort those, it performs 1.5 times slower than the approach using sets. My approach above seems to perform 1.5 times faster than the approach using sets. If the arrays are guaranteed to be sorted already, my approach will perform even better yet (almost 4 times as fast as the version using sets), since no sorting is required.
Update:
This did not eliminate duplicates, so I added the loop at the end of the routine. Now it is only 3 times as fast as the approach using sets, but still...

Iterate over array1 & search for it in array2. If it is found, add it to array3 if it does not have it already.
for (MyObject* obj in array1)
{
if([array2 containsObject:obj] && ![array3 containsObject:obj])
[array3 addObject:obj];
}
If your array1 does not have duplicate items, you don't need the 2nd check.

Related

How can I get all the possibles combinations of numbers from an array in Objective-C [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Generating permutations of NSArray elements
Let's say that I have
[1,2]
And I want to get
{1}
{2}
{1, 2}
{2, 3}
I think the name of the thing you're looking for is 'power set'. It sounded fun, so here's a crack at it. I relied on this very concise article for the algorithm. I'm not sure if this is efficient (...actually, I'm sure this is inefficient) over large sets.
// answer the powerset of array: an array of all possible subarrays of the passed array
- (NSArray *)powerSet:(NSArray *)array {
NSInteger length = array.count;
if (length == 0) return [NSArray arrayWithObject:[NSArray array]];
// get an object from the array and the array without that object
id lastObject = [array lastObject];
NSArray *arrayLessOne = [array subarrayWithRange:NSMakeRange(0,length-1)];
// compute the powerset of the array without that object
// recursion makes me happy
NSArray *powerSetLessOne = [self powerSet:arrayLessOne];
// powerset is the union of the powerSetLessOne and powerSetLessOne where
// each element is unioned with the removed element
NSMutableArray *powerset = [NSMutableArray arrayWithArray:powerSetLessOne];
// add the removed object to every element of the recursive power set
for (NSArray *lessOneElement in powerSetLessOne) {
[powerset addObject:[lessOneElement arrayByAddingObject:lastObject]];
}
return [NSArray arrayWithArray:powerset];
}
If you think this is a keeper, you could make it a category method on array and drop the parameter. Test it like this...
NSLog(#"empty = %#", [self powerSet:[NSArray array]]);
NSLog(#"one item = %#", [self powerSet:[NSArray arrayWithObject:#"a"]]);
NSLog(#"two items = %#", [self powerSet:[NSArray arrayWithObjects:#"a", #"b", nil]]);
NSLog(#"three items = %#", [self powerSet:[NSArray arrayWithObjects:#"a", #"b", #"c", nil]]);
I did only these tests, and the output looked good. Spoiler alert: the three item test looks roughly like this on my console (with \n's removed):
three items = ((),
(a),
(b),
(a,b),
(c),
(a,c),
(b,c),
(a,b,c))

error in array cleaning method

I am attempting to use this array cleaning method, and there seems to be an error. I can't spot it, I know the array goes in with 3116 items, comes out with 3116 (and I know for a fact there are three duplicates.
Please advice, thanks!
-(NSArray*) removeDuplicates:(NSArray*)inputArray{
NSMutableArray *arrayToClean = [NSMutableArray arrayWithArray:inputArray];
for (int i =0; i<[arrayToClean count]; i++) {
for (int j=(i+1); j < [arrayToClean count]; j++) {
if ([[arrayToClean objectAtIndex:i] isEqual:[arrayToClean
objectAtIndex:j]]) {
[arrayToClean removeObjectAtIndex:j];
j--;
}
}
}
NSArray *arrayToReturn = [NSArray arrayWithArray:arrayToClean];
return arrayToReturn;
}
NSSet will make this a lot easier:
-(NSArray *)removeDuplicates:(NSArray *)inputArray {
NSSet *unique = [NSSet setWithArray:inputArray];
return [unique allObjects];
}
Please note that a set has no guaranteed order. If you need the objects in the array to be in a specific order then you should sort the resulting array as needed.
It may also be appropriate to use an NSSet instead of the original array, then you don't need to worry about duplicates at all. But this depends on the other needs of your array.
Hey You can use another alternative for this.You can use the NSSet here for this task.
NSSet declares the programmatic interface for static sets of distinct objects
You can use sets as an alternative to arrays when the order of elements isn’t important and performance in testing whether an object is contained in the set is a consideration—while arrays are ordered, testing for membership is slower than with sets.
You Just need To call below method.
-(NSArray *)removeDuplicates:(NSArray *)inputArray {
NSSet *finalData = [NSSet setWithArray:inputArray];
return [finalData allObjects];
}
If really face any problem in above way of cleaning ducplicates then you can try another Alterantive.
-(NSArray *)removeDuplicates:(NSArray *)inputArray {
NSMutableArray *inputArray1=[NSMutableArray arrayWithArray:inputArray];
NSMutableArray *finalARray=[[NSMutableArray alloc]init];
for (id obj in inputArray1)
{
if (![finalARray containsObject:obj])
{
[finalARray addObject: obj];
}
NSLog(#"new array is %#",finalARray);
}
return finalARray;
}
I hope it may help you ...
Here is a helper function I had in a previous project to do the exact same thing
- (NSMutableArray *)removeDuplicates:(NSMutableArray *)sortedArray{
NSMutableSet* valuesAdded = [NSMutableSet set];
NSMutableArray* filteredArray = [[NSMutableArray alloc] init];
NSString* object;
/* Iterate over the array checking if the value is a member of the set. If its not add it
* to the set and to the returning array. If the value is already a member, skip over it.
*/
for (object in sortedArray){
if (![valuesAdded member:object]){
[valuesAdded addObject:object];
[filteredArray addObject:object];
}
}
return filteredArray;
}

How is the code for separation of single array into two arrays?

I am getting below response into the nsarray when I used the JSON parsing from my required URL but here I don't like to get 2,1,4,4,6,5,8,7,10,9,12 and 11 in single array I have to get total response into two arrays I mean one array set will consists 2,4,6,8,10 and other array set must be 3,5,7,9 and 11.
So how is the code for separation of single array response into two arrays in iPhone?
"(\n 2,\n 1\n)",
"(\n 4,\n 3\n)",
"(\n 6,\n 5\n)",
"(\n 8,\n 7\n)",
"(\n 10,\n 9\n)",
"(\n 12,\n 11\n)"
If you combine every number into one large array, you could feasibly test if each number is even or odd with a simple if-else in a for-in loop. Maybe like this:
-(NSArray*)parseJSONIntoArrays:(NSArray*)array {
NSMutableArray *evenNumbers = [[NSMutableArray alloc]init];
NSMutableArray *oddNumbers = [[NSMutableArray alloc]init];
for (NSNumber *number in array) {
if (([number intValue] %2) == 0) {
//even
[evenNumbers addObject:number];
}
else {
//odd
[oddNumbers addObject:number];
}
}
return [[NSArray alloc]initWithObjects:evenNumbers, oddNumbers, nil];
}
To split an array, you usually need to loop through all of the values and use an IF ELSE structure to decide which array to put the values in. Also, you need to use NSMutableArray instead of NSArray. Something like this:
NSMutableArray *evenNumbers = [NSMutableArray new];
NSMutableArray *oddNumbers = [NSMutableArray new];
for (NSNumber *value in myArray) {
if ([value intValue] % 2 == 0) {
[evenNumbers addObject:value];
} else {
[oddNumbers addObject:value];
}
}

How do I find (not remove) duplicates in an NSDictionary of NSArrays?

The title pretty much says it all, but just to clarify: I have an NSMutableDictonary containing several NSMutableArrays. What I would like to do is find any value that is present in multiple arrays (there will not be any duplicates in a single array) and return that value. Can someone please help? Thanks in advance!
Edit: For clarity's sake I will specify some of my variables:
linesMutableDictionary contains a list of Line objects (which are a custom NSObject subclass of mine)
pointsArray is an array inside each Line object and contains the values I am trying to search through.
Basically I am trying to find out which lines share common points (the purpose of my app is geometry based)
- (NSValue*)checkForDupes:(NSMutableDictionary*)dict {
NSMutableArray *derp = [NSMutableArray array];
for (NSString *key in [dict allKeys]) {
Line *temp = (Line*)[dict objectForKey:key];
for (NSValue *val in [temp pointsArray]) {
if ([derp containsObject:val])
return val;
}
[derp addObjectsFromArray:[temp pointsArray]];
}
return nil;
}
this should work
If by duplicates you mean returning YES to isEqual: you could first make an NSSet of all the elements (NSSet cannot, by definition, have duplicates):
NSMutableSet* allElements = [[NSMutableSet alloc] init];
for (NSArray* array in [dictionary allValues]) {
[allElements addObjectsFromArray:array];
}
Now you loop through the elements and check if they are in multiple arrays
NSMutableSet* allDuplicateElements = [[NSMutableSet alloc] init];
for (NSObject* element in allElements) {
NSUInteger count = 0;
for (NSArray* array in [dictionary allValues]) {
if ([array containsObject:element]) count++;
if (count > 1) {
[allDuplicateElements addObject:element];
break;
}
}
}
Then you have your duplicate elements and don't forget to release allElements and allDuplicateElements.

Restrict Duplicate entry in NSArray

I have an array, which contains some duplicate entries.
Firstly, is there any way to restrict duplicate entries when data getting inserted?
Secondly, if an array already having duplicate values than in some other way, we can retrieve only unique values from that array, I heard about NSSet about this, but I have no idea how to use it.
Don't use an NSSet.
You can only insert elements upon creation and cannot change the elements contained after you have created it.
If you want to add and remove objects on the fly, you can use an NSMutableSet.
Here is a demo of how to use it both NSSet and NSMutableSet, then converting the NSSet back to an NSArray (incase you want to do that):
- (void) NSMutableSetPrintTest
{
NSMutableSet *mutableSet = [[NSMutableSet alloc] init];
NSLog(#"Adding 5 objects (3 are duplicates) to NSMutableSet");
NSString *firstString = #"Hello World";
[mutableSet addObject:firstString];
[mutableSet addObject:#"Hello World"];
[mutableSet addObject:#"Goodbye World"];
[mutableSet addObject:#"Goodbye World"];
[mutableSet addObject:#"Goodbye World"];
NSLog(#"NSMutableSet now contains %d objects:", [mutableSet count]);
int j = 0;
for (NSString *string in mutableSet) {
NSLog(#"%d: %# <%p>", j, string, string);
j++;
}
NSLog(#"Now, if we are done adding and removing things (and only want to check what is in the Set) we should convert to an NSSet for increased performance.");
NSSet *immutableSet = [NSSet setWithSet:mutableSet];
NSLog(#"NSSet now contains %d objects:", [immutableSet count]);
int i = 0;
for (NSString *string in immutableSet) {
NSLog(#"%d: %# <%p>", i, string, string);
i++;
}
[mutableSet release]; mutableSet = nil;
NSLog(#"Now, if we are done with the sets, we can convert them back to an NSArray:");
NSArray *array = [immutableSet allObjects];
NSLog(#"NSArray contains %d objects", [array count]);
int k = 0;
for (NSString *string in array) {
NSLog(#"%d: %# <%p>", k, string, string);
k++;
}
}
NSMutableSet is probably the most logical thing to use.
However, be warned that a set does not maintain order of its elements (since a set, by definition, is unordered).
If that's a problem for you, then you have a couple of options:
duplicate set functionality with an NSMutableArray by invoking containsObject: before every call to addObject: (doable, but potentially slow, since arrays have O(n) search time)
use another object.
If you go with the second option, I would recommend taking a look at the excellent CHDataStructures framework, which has a subclass of NSMutableSet called CHOrderedSet, which is a set that maintains insertion order. (And since it's a subclass, it has the exact same API as an NSMutableSet)
If you've heard about NSSet, did you read the documentation? The API is similar to NSArray and very straightforward. Just like NSArray vs. NSMutableArray, you would use NSMutableSet if you need on the fly membership tests.