How do I get rid of duplicates in an array? - objective-c

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

Related

String contain string

after a decent search and could not find solution (probably i missed something...):
i have an array with objects, the object is AddressCard and one if the properties is name.
so i send to my function string and with for statement looking all the matches inside my object collection array who contain AddressCArd object (bookArray) and if there is match i want to add this object to an array asnd return this array:
-(NSMutableArray *) lookup:(NSString *) name
{
NSMutableArray arr = [NSMutableArray array];
for(AddressCard *card in bookArray}
{
if([card.name rangeOfString: name].location == NSNotfound)
{
[arr addObject: card];
}
}
return arr;
}
You can do as this:
-(NSMutableArray *) lookup:(NSString *) name {
NSMutableArray *arr = [NSMutableArray array];
for(AddressCard *card in bookArray) {
//if([card.name isEqualToString:name]) {
if([[card.name capitalizedString] rangeOfString:[name capitalizedString]].location != NSNotFound)
[arr addObject:card];
}
}
return arr;
}

loop through array of dictionaries to find a value

I have an array of dictionaries that I would like to go through to find a matching value that I can then Count == Nth item of the array
Each item of the array looks like this
HMOD = 0;
MID = 39;
MOD = SOMETHING; // looking for this value
ID = 50;
So I would like to create a loop that goes through the array until it finds the matching value, then I use the number in the count as an reference to Index path in the next view..
I have written this peice of code which dosnt work... but hopefully it gives you an idea of the loop I am trying to create.
int count = 0;
while (singleName != [[ModArray valueForKey:#"MOD"] objectAtIndex:count]) {
count ++;
NSLog(#"%i", count);
}
SingleName is a NSString that I am using to match the MOD value in ModArray...
Any help would be greatly appreciated.
Here is a simpler solution by using valueForKey on the array of dictionaries,
Assuming that your modArray is like this,
NSArray *modArray = [NSArray arrayWithObjects:[NSDictionary dictionaryWithObject:#"0" forKey:#"HMOD"],
[NSDictionary dictionaryWithObject:#"39" forKey:#"MID"],
[NSDictionary dictionaryWithObject:#"something" forKey:#"MOD"],
[NSDictionary dictionaryWithObject:#"50" forKey:#"ID"], nil];
And singleName has a value as "something"
NSString *singleName = #"something";
Fetch the array from modArray which has an object with key as "MOD",
NSArray *array = [modArray valueForKey:#"MOD"];
Check if singleName is present in this array. If yes, then get the first index of that object which will be same as the index of dictionary with key "MOD" in modArray.
if ([array containsObject:singleName]) {
NSLog(#"%d", [array indexOfObject:singleName]);
} else {
NSLog(#"%# is not present in the array", singleName);
}
Update:
If you want to do it in your way, only mistake was you were using != whereas you should have used isEqualToString. You should have done like this,
int count = 0;
while (![singleName isEqualToString:[[modArray valueForKey:#"MOD"] objectAtIndex:count]]) {
count ++;
NSLog(#"%i", count);
}
Your code looks all inside out. You state you have an array of dictionaries. Assuming ModArray is the array (based on the name) you might do this:
NSUInteger count = 0;
for (NSDictionary *dict in ModArray) { // iterate through the array
NSString *mod = dict[#"MOD"]; // get the value for MOD
if ([mod isEqualToString:singleName]) { // compare the two strings
break; // they match so exit the loop
}
count++
}
// count has the index of the dictionary with the matching MOD value
Edit: Based on ACB correcting my misunderstanding of NSArray valueForKey:, the only real issue is your use of using != to compare the two strings.
- This is Helpful when you search from Dictionary.
NSMutableArray *contentList;
NSMutableArray *filteredContentList;
BOOL isSearching;
// firstSection is array which already filled.
// contentList array for value of particular key
// filteredContentList is search array from actual array.
- (void)searchTableList {
NSString *searchString = searchBar.text;
NSPredicate *filterPredicate = [NSPredicate predicateWithFormat:#"frame_code beginswith[c] %#", searchString];
NSArray *filteredArr = [firstSection filteredArrayUsingPredicate:filterPredicate];
if(contentList.count > 0)
[contentList removeAllObjects];
[filteredContentList addObjectsFromArray:filteredArr];
}
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar1 {
if ([searchBar1.text length] != 0)
isSearching = YES;
else
isSearching = NO;
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
NSLog(#"Text change - %d",isSearching);
//Remove all objects first.
[filteredContentList removeAllObjects];
if([searchText length] != 0) {
isSearching = YES;
[self searchTableList];
}
else {
isSearching = NO;
}
[tblFrameList_SComplete reloadData];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
NSLog(#"Cancel clicked");
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
NSLog(#"Search Clicked");
[self searchTableList];
}

How do I compare if *ALL* strings of a NSArray are equal ?

How do I compare if all strings of a NSArray are equal ?
Should I scan the array for each string ?
thanks
You could do this by creating a new set from the array. The set will only contain unique entries so if the number of elements in the set is 1 then all items in the array was equal.
NSSet *uniqueItems = [NSSet setWithArray:yourArray];
if ([uniqueItems count] < 2) {
// All items in "yourArray" are the same (no matter how many they are)
}
In the above example I'm considering an empty set (meaning an empty array) as a being unique as well. If you don't then you can change the if-statement to if ([uniqueItems count] == 1) { ... }
This will also work for any object, not just strings.
The NSArray class is general-purpose so it won't contain functionality to perform this, so yes, you'll have to check each string yourself.
trojanfoe is right. You can enhance NSArray with category and do something like this ...
NSArray *array = #[ #"A", #"B", #"C" ];
__block BOOL allObjectsAreEqual = YES;
if ( array.count > 1 ) {
NSString *firstObject = array[0];
[array enumerateObjectsUsingBlock:^void(id obj, NSUInteger idx, BOOL *stop) {
if ( idx == 0 ) {
return;
}
if ( ( allObjectsAreEqual = [firstObject isEqualToString:obj] ) == NO ) {
*stop = YES;
}
}];
// And here check for allObjectsAreEqual ...
... there're many ways how to do this.
Are you wanting to check whether all the strings are equal to each other?
#interface NSArray (MyAdditions)
- (BOOL) isFilledWithEqualObjects {
if (!self.count) return YES;
id firstObject = [self objectAtIndex:0];
for (id obj in self) {
// Avoid comparing firstObject to itself (and any other pointers to
// firstObject)
if (firstObject == obj) continue;
if (![firstObject isEqual:obj]) return NO;
}
return YES;
}
#end
That example uses -isEqual:, to work with any kind of object. If you know the contents are strings, you can use -isEqualToString: instead:
if (![firstObject isEqualToString:obj]) return NO;

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

Two dimensional array search in 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");