Two dimensional array search in objective c - objective-c

i want to ask question that how can we search in a plist which is of array type and has elements of array type as well. i am searching from a plist which is of string element type and its working fine, but i am not able to search when it has array elements in the plist.
Regards!

- (BOOL)searchArray:(NSArray *)array forObject:(id)object {
if ([array containsObject:object]) {
return TRUE;
}
for (id elem in array) {
if ([elem isKindOfClass:[NSArray class]]) {
if ([self searchArray:elem forObject:object]) {
return TRUE;
}
}
}
return FALSE;
}
Will handle a two-dimensional array as well as any other depth.

You question is not very clear but if you're looking for a way to locate an object in a NSArray containing NSArrays containing objects (NSStrings), here's an example:
NSArray * l20 = [NSArray arrayWithObjects:#"One", #"Two", nil];
NSArray * l21 = [NSArray arrayWithObjects:#"Three", #"Four", nil];
NSArray * ll = [NSArray arrayWithObjects:l20, l21, nil];
for(id l1obj in ll)
for(id l2obj in l1obj)
if([l2obj isEqualToString:#"Three"])
NSLog(#"Found object three");

Related

How to fetch an object from array of dictionaries in ios

I have an array of dictionaries with multiple keys and objects of different types. I want to fetch only one of the object and compare with the other object. I have been trying with for each loop but not bee able to do so.
Iterate the array:
for (NSDictionary *dict in array) {
then iterate the keys in the dictionary
NSArray *keys = [dict allKeys];
for (NSString *key in keys) {
then extract the value for the key:
id obj = dict[key];
Then test the object type and compare with the other object:
if ([obj isKindOfClass:[NSString class]]) {
NSString *stringObj = (NSString *)obj;
if ([stringObj isEqualToString:otherObj]) {
NSLog(#"Object equals dictionary entry %#", key);
}
} else if ([obj isKindOfClass:[NSNumber class]]) {
NSNumber *numberObj = (NSNumber *)obj;
if ([numberObj isEqual:otherObj]) {
NSLog(#"Object equals dictionary entry %#", key);
}
} else // etc.
first get the dictionary from array
NSDictionary *dict=[yourarray objectAtIndex:index];
then get the object from dictionary
NSString *yourValue=[dict objectForKey:#"Your KeyValue"];
In case of for each loop
for (NSDictionary *dict in yourArray) {
NSString *yourValue=[dict objectForKey:#"Your KeyValue"];
NSLog(#"%#",yourValue);
}

How do I get rid of duplicates in an array?

I'd like to do this without using NSSet. I know it's probably quicker but I'm trying to understand how arrays work. This is the mutable array I'm working with, it has duplicate values.
NSMutableArray *mainArray = #[#"a",#"a",#"b",#"c",#"d",#"d"];
NSLog(#"mainArray = %#", mainArray);
- (NSArray *)arrayWithUniqueObjectsFromArray:(NSArray *)array
{
NSMutableArray *uniqueObjects = [NSMutableArray new];
for(id obj in array) {
if([uniqueObjects containsObject:obj] == NO) {
[uniqueObjects addObject:obj];
}
}
return uniqueObjects;
}

Compare two arrays with the same value but with a different order

I have 2 nsarray, with the same values but in different order.
NSArray * array1 = {0,1,2,3}
NSArray * array2 = {2,3,1,0}
I need a method to determinate if two arrays have the same values in a different order.
Kind of
-(BOOL) isSameValues:(NSArray*)array1 and:(NSArray*)array2;
You can use NSCountedSet for that purpose:
- (BOOL)isSameValues:(NSArray*)array1 and:(NSArray*)array2
{
NSCountedSet *set1 = [NSCountedSet setWithArray:array1];
NSCountedSet *set2 = [NSCountedSet setWithArray:array2];
return [set1 isEqualToSet:set2];
}
NSCountedSet is a collection of different objects, where each object has an associated counter with it. Therefore the result for
NSArray *array1 = #[#0,#1,#2,#3];
NSArray *array2 = #[#2,#3,#1,#0];
is YES, but for
NSArray *array1 = #[#1,#1,#3,#3];
NSArray *array2 = #[#3,#3,#3,#1];
the result is NO.
Update: this will not work if arrays have duplicate elements!
You could create two NSSets with those arrays and the compare them.
NSArray * array1 = #[#0,#1,#2,#3];
NSArray * array2 = #[#2,#3,#1,#0];
NSSet *set1 = [NSSet setWithArray:array1];
NSSet *set2 = [NSSet setWithArray:array2];
NSLog(#"result %#", [set1 isEqualToSet:set2] ? #"YES" : #"NO");
if ([[NSSet setWithArray:array1] isEqualToSet:[NSSet setWithArray:array2]]) {
// the objects are the same
}
Take total no of elements. Have a counter. And put double 'for loop' to parse through each and every element of each other. Increment the counter at each matching.
Note : This is valid when all elements are unique.
If different or you don't know, sort them and match one to one.
An other way would be to use a NSHashTable.
- (BOOL)array:(NSArray *)array1 containsTheSameObjectsAsArray:(NSArray *)array2 {
if (array1.count != array2.count) {
return NO;
}
NSHashTable *table = [[NSHashTable alloc] initWithOptions:NSHashTableWeakMemory
capacity:array1.count];
for (NSObject *object in array1) {
[table addObject:object];
}
for (NSObject *object in array2) {
if (![table containsObject:object]) {
return NO;
}
}
return YES;
}
Note that NSHashTable requires iOS 6+

Better solution for this 2x fast-enumeration?

I'm looping through an array and comparing the objects tag property in this array with the objects in another array.
Here's my code:
NSArray *objectsArray = ...;
NSArray *anotherObjectArray = ...;
NSMutableArray *mutableArray = ...;
for (ObjectA *objectA in objectsArray) {
for (ObjectZ *objectZ in anotherObjectArray) {
if ([objectA.tag isEqualToString:objectZ.tag]) {
[mutableArray addObject:objectA];
}
}
}
Is there a better way to do this?
Please note the tag property is not an integer, so have to compare strings.
You can do this by iterating over each array once, rather than nesting:
NSMutableSet *tagSet = [NSMutableSet setWithCapacity:[anotherObjectArray count]];
for(ObjectZ *objectZ in antherObjectArray) {
[tagSet addObject:objectZ.tag];
}
NSMutableArray *output = [NSMutableArray mutableArray];
for(ObjectA *objectA in objectsArray) {
if([tagSet containsObject:objectA.tag]) {
[output addObject:objectA];
}
}
May be you can use [NSArray filteredArrayUsingPredicate:]; - http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/NSArray.html
But you may have to tweak for property tag yourself.
NSArray *objectsArray = [NSArray arrayWithObjects:#"Miguel", #"Ben", #"Adam", #"Melissa", nil];
NSArray *tagsArray = [NSArray arrayWithObjects:#"Miguel", #"Adam", nil];
NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF IN %#", tagsArray];
NSArray *results = [objectsArray filteredArrayUsingPredicate:sPredicate];
NSLog(#"Matched %d", [results count]);
for (id a in results) {
NSLog(#"Object is %#", a);
}
Hope this helps
Well, the simplest change (as there can only be one match per objectA) then you could do a break after your [mutableArray addObject:objectA]. When a match occurs, that would reduce the inner loop by 50%.
More dramatically, if you're doing this a lot and the order of anotherObjectArray doesn't matter, would be to invert your anotherObjectArray data structure and use a dictionary, storing the objects by tag. Then you just iterate over objectA asking if its tag is in the dictionary of ObjectZs.
Thanks for all the answers. While I have accepted the NSMutableSet solution, I actually ended up going with the following, as it turned out it was a tiny bit faster:
NSMutableDictionary *tagDictionary = [NSMutableDictionary dictionaryWithCapacity:[anotherObjectArray count]];
for (ObjectZ *objectZ in anotherObjectArray) {
[tagDictionary setObject:objectZ.tag forKey:objectZ.tag];
}
for (ObjectA *objectA in objectsArray) {
if ([tagDictionary objectForKey:objectA.tag]) {
[direction addObject:objectA];
}
}

Initing a NSArray with a method which returns an NSArray?

I have a method that returns an NSArray:
-(NSArray *)arrayMethod {
if (x == 2) { return array1; } else { return array2; }
}
Can I do something like:
NSArray *finalArray = [NSArray arrayWithObject:[self arrayMethod]];
Thanks already.
Use arrayWithArray instead arrayWithObject.
NSArray *finalArray = [NSArray arrayWithArray:[self arrayMethod]];
OR alternatively
NSArray *tempArray = [self arrayMethod];
NSArray *finalArray = [NSArray arrayWithArray:tempArray];
You want to use this instead:
arrayWithArray: Creates and returns an array containing the
objects in another given array.
(id)arrayWithArray:(NSArray *)anArray