objective-c , Finding objects from array - objective-c

I have an array that contains some objects;
example:
NSArray*arr=[NSMutableArray arrayWithObjects:#1,#5,#7,#6 nil];
How I could find, for example if the array contains the number 1 and 7 without creating a loop.
Is there such a function?
For example returns a Boolean value or something?

Sure thing!
You can use this method
(BOOL)containsObject:(ObjectType)anObject;
or somethings else:
(NSUInteger)indexOfObject:(ObjectType)anObject;
(NSUInteger)indexOfObject:(ObjectType)anObject inRange:(NSRange)range;
Have fun.

Use indexOfObject to find if an element is present in your array or not :
NSNumber *num=[NSNumber numberWithInteger:7];
NSInteger anIndex=[myArray indexOfObject:num];
if(NSNotFound == anIndex) {
NSLog(#"not found");
}
Hope this helps.

Related

How to find if an object of a class with same data already exists in a NSMutableArray?

I apologize for this basic question, but I am 2-month new to obj-c.
Problem:
I am not able to find if an object with same data already exists in the NSMutableArray.
What I am doing?
ScanDigInfoForTable* sfile = [[ScanDigInfoForTable alloc]init];
sfile.data = "myData";
int inde = [_DataList indexOfObject:sfile] ;
if(inde == -1)
[_DataList addObject:sfile];
ScanDigInfoForTable* sfile2 = [[ScanDigInfoForTable alloc]init];
sfile2.data = "myData";
inde = [_DataList indexOfObject:sfile2] ;
if(inde == -1)
[_DataList addObject:sfile2];
Issue:
The _DataList get 2 objects instead of 1. Many thanks in advance for your attention.
S.P: I already know that I may traverse the whole array in a loop in order to check the data already exists. Looking for a better solution as the array may have thousands of records.
Well, comparing two custom objects is really not that simple for the simple fact there is no defined way to declare equality. It is individual choice to define the rules for equality for the objects they are creating.
In your case, it would be two step process:
Step 1: Implement isEqual: in your ScanDigInfoForTable class. Assuming ScanDigInfoForTable is a model class and that it has three string properties - code, data & itemID (you can have any type).
- (BOOL)isEqual:(ScanDigInfoForTable *)other {
return [self.code isEqualToString:other.code] && [self.data isEqualToString:other.data] && [self.itemID isEqualToString:other.itemID];
}
Step 2: Call containsObject: method on NSMutableArray. This method would internally call isEqual: to give you the results based on the rules you defined.
// If the object does not exist in the list, we add it
if (![_DataList containsObject:sfile2]) {
[_DataList addObject:sfile2];
}
In Objective-C object equality is determined by the methods -isEqual: and -hash.
When testing object membership in a collection the items of the collection are sent isEqual:. The default implementation only compares the addresses of objects, which is why you are seeing duplicates. Your objects do no provide their own implementation of equality based on the data they contain.
To fix this you can override isEqual: to compare objects based on the data they represent. Using your example in your question, this could just be:
- (BOOL) isEqual:(id)object {
BOOL result = N0;
if (object != self){
if ([object isKindOfClass:[self class]]){
result = [[self data] isEqual:[(ScanDigInfoForTable *)object data]];
}
} else {
result = YES;
}
return result;
}
Mike Ash has a great article about implementing equality. In general, if you are implementing a custom class you should make equality a part of that.
You can user filteredArrayUsingPredicate for example
NSArray * matches = [_DataList filteredArrayUsingPredicate:
[NSPredicate predicateWithFormat:#"data == %# ",sfile2.data]];
if(matches.count == 0) {
[_DataList addObject:sfile2];
}
Something like this?
NSMutableSet* set1 = [NSMutableSet setWithArray:array1];
NSMutableSet* set2 = [NSMutableSet setWithArray:array2];
[set1 intersectSet:set2]; //this will give you only the obejcts 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 also set2 doesn't have to be mutable, might as well use just
NSSet* set2 = [NSSet setWithArray:array2];

Adding items from 1 array 2 another filtered by dictionary key

I've been trying to logically think about this for a while now and usually I can solve it by writing it out or thinking about it while doing other stuff not associated with programming. However everything I try isn't working. So basically I have 2 NSArrays, which are both populated from 2 different plists. Each array is filled with all dictionaries: all have the same keys, and all have the same identical structure, but some may have information associated with a key that some don't. I basically need to check each item in array1 and see if it exists in array2 and if it does NOT exist in array2 then add it to array1 (or array3 seeing how you can't mutate an array while iterating through it). I need it to see if it exists by a specific key "name_key".
So... In short my end result needs to be an NSArray with all objects from both arrays without having objects with duplicate names (from the dictionaries name_key).
Below is my actual code that doesn't work.
IN CODE BELOW: originalWhiskiesListArray = array1
newWhiskiesListArray = array2
combinedWhiskiesListArray = array3 (because you can't mutate an array while iterating through it.
BOOL whiskyExists = YES;
for (NSDictionary *newWhisky in newWhiskiesListArray) {
for (NSDictionary *originalWhisky in originalWhiskiesListArray) {
NSString * newWhiskyNameString = [[newWhisky objectForKey:NAME_KEY] lowercaseString];
NSString * origWhiskyNameString = [[originalWhisky objectForKey:NAME_KEY] lowercaseString];
//Compare lowercase strings and if they don't match then add them to the original plist array.
if ([newWhiskyNameString isEqualToString:origWhiskyNameString]) {
whiskyExists = YES;
break;
} else {
whiskyExists = NO;
break;
//NSLog(#"Whisky names do not match. New Whisky: %# Old Whisky: %#",[newWhisky objectForKey:NAME_KEY],[originalWhisky objectForKey:NAME_KEY]);
//doesn't match so add it
}
}
if (whiskyExists == NO) {
[combinedWhiskiesListArray addObject:newWhisky];
NSLog(#"newWhisky added");
whiskyExists = YES;
}
}
Can either of the whiskey name strings be nil? If so then this breaks the isEqualToString comparison because you can always message nil which returns NO.
Also I believe that the breaks are wrong. You only need to exit the inner loop in case you encounter a match. If not you have to keep going until the end of the inner loop.
If I'm understanding you correctly, you can just add all the values from each dictionary to an NSMutableSet, which won't add an item if it already exists in the set. You can then convert the set back to an array with the NSSet method allObjects.

check and remove a particular string from nsmutable array without index

In Xcode, I store some NSString in NSMutableArray.
Hello
Here
MyBook
Bible
Array
Name2
There
IamCriminal
User can enter string.
Name2
I need to delete that particular string from NSMutableArray without knowing index of the string. I have some idea that, Use iteration. Any other Best way. Plz Give with sample codings.
you can use containsObject method in an NSMutableArray
if ([yourArray containsObject:#"object"]) {
[yourArray removeObject:#"object"];
}
Swift:
if yourArray.contains("object") {
yourArray = yourArray.filter{ $0 != "object" }
}
[array removeObject:#"Name2"];
The documentation for NSMutableArray’s removeObject: method states:
matches are determined on the basis of an object’s response to the
isEqual: message
In other words, this method iterates over your array comparing the objects to #"Name2". If an object is equal to #"Name2", it is removed from the array.
[array removeObject:#"name2"];
You can try this
for(NSString *string in array)
{
if([[string lowercasestring] isEqualToSring:[yourString lowercasestring]])
{
[array removeObject:string];
break;
}
}
YOu can simply use
[yourArray removeObject:stringObjectToDelete];
This method uses indexOfObject: to locate matches and then removes them by using removeObjectAtIndex:. Thus, matches are determined on the basis of an object’s response to the isEqual: message. If the array does not contain anObject, the method has no effect.
Try this,
BOOL flag = [arrayName containsObject:Str];
if (flag == YES)
{
[arrayName removeObject:Str];
}

Check for item in array without looping

I have an array and I want to check if one string is in the array, without looping. Just using "if's" I know if some string exists or not in the array.
Is there any possibility?
Use -[NSArray containsObject:].
(You don't have to write the loop yourself, but of course NSArray almost certainly has to use a loop internally.)
if ([array containsObject:string])
NSLog(#"Yes, the array contains my string.")
What about
if ([yourArray containsObject:#"string"]) {
}
??
NSarray *theArray; // assume exists
if ( [theArray containsObject:someString] )
{
...
}

How do Arrays behave in Objective-C?

I've always had my doubts about Arrays.
If an Array's count is 7, and I replace the SECOND elements with 'NULL', does it still have count 7?
If an Array's count is 7, and I replace the LAST elements with 'NULL', does it still have count 7? Or will it have count 6?
I need to know this behavior to make a function that removes the first element of the Array (place '0'), and the other elements of the Array swap one place to the front.
- (void) eat {
[foodArray replaceObjectAtIndex:0 withObject:NULL];
for (int i = 0; i<[foodArray count]-1; ++i){
[foodArray replaceObjectAtIndex:i withObject:[foodArray objectAtIndex:i+1]];
}
[foodArray replaceObjectAtIndex:[foodArray count]-1 withObject:NULL];
}
Would that work?
(Thanks!)
Edit: I've just noticed the first line isn't necessary, as I'm already replacing the first element later. Am I wrong?
If you want to remove an object from an array, just use [foodArray removeObjectAtIndex:]. The way you're doing it you're just leaving a null value in the array.
Just remove the item:
- (void) eat {
[foodArray removeObjectAtIndex:0];
}
Inorder to add/remove array elements the array must be mutable: NSMutableArray so foodArray must be a NSMutableArray.
Trying to keep NULL in an array is bad idea in general.
If you need to use some kind of placeholder - it's better to use an instance of NSNull class.
Later you can check type of the object using class name check:
if( [objectFromArray isKindOfClass:[NSNull class]] == YES )
{ // This is NSNull instance, not real object }