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

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;

Related

NSDictionary and comparing SetObjects

Hi I'm wondering how to compare the contents of the setObjects stored with keys in an NSDictionary: Here's my code I'm working with:
[INNumbers setObject:#"0,1,2,3,4,5,6,7" forKey:#"0"];
[INNumbers setObject:#"4,5,6,7,8,9,10,11" forKey:#"1"];
I'm wonder how I would compare the 2 keys and find if there are similar numbers like if 7 occurs in both?
//this will get the numbers in the keys for me
id number1 = [INNumbers objectForKey:#"0"];
id number2 = [INNumbers objectForKey:#"1"];
but I'm not sure how to compare what number1 and number2 retrieve.
If I was not force to use strings, I would do it this way:
NSArray *nums0 = #[#1,#2,#3];
NSArray *nums1 = #[#3,#4,#5];
NSMutableSet *intersection = [NSMutableSet setWithArray:nums0];
[intersection intersectSet:[NSSet setWithArray:nums1]];
NSArray *numsInCommon = [intersection allObjects];
numsInCommon will contain #3 that is the number that is in both arrays
In your example, the values stored in the dictionary are string literals, which are hard to parse and test for membership tests repeatedly. Perhaps you wanted to use NSSets:
#import <Foundation/Foundation.h>
int main()
{
NSSet *numbers1 = [NSSet setWithObjects:#0, #1, #2, nil];
NSSet *numbers2 = [NSSet setWithObjects:#0, #4, #5, nil];
if([numbers1 intersectsSet : numbers2]) {
NSLog(#"The two sets have at least one element in common!");
/* Let's obtain the intersection: */
NSSet *common = [numbers1 objectsPassingTest:^BOOL(id obj, BOOL *stop) {
if ([numbers2 containsObject:obj]) {
return YES;
} else {
return NO;
}
}];
for (id o in common) {
NSLog(#"%#", o);
}
}
return 0;
}

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+

Searching for a string within an array for an NSRange

I am trying to search for a string within an array, but I only want to search the last five objects in the array for the string.
I have been fiddling with every parameter I can find on NSRange to no avail.
I would post some example code, but I can't even get out the line I need, whether its through introspection, enumeration, or just some NSRange call that I missed.
If your array elements are strings that you searched for, you can directly check the array as follows:
if ([yourArray containsObject:yourString])
{
int index = [yourArray indexOfObject:yourString];
if (index>= yourArray.count-5)
{
// Your string matched
}
}
I like indexesOfObjectsWithOptions:passingTest: for this. Example:
NSArray *array = #[#24, #32, #126, #1, #98, #16, #67, #42, #44];
// run test block on each element of the array, starting at the end of the array
NSIndexSet *hits = [array indexesOfObjectsWithOptions:NSEnumerationReverse passingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
// if we're past the elements we're interested in
// we can set the `stop` pointer to YES to break out of
// the enumeration
if (idx < [array count] - 5) {
*stop = YES;
return NO;
}
// do our test -- if the element matches, return YES
if (40 > [obj intValue]) {
return YES;
}
return NO;
}];
// indexes of matching elements are in `hits`
NSLog(#"%#", hits);
Try this :-
//Take only last 5 objects
NSRange range = NSMakeRange([mutableArray1 count] - 5, 5);
NSMutableArray *mutableArray2 = [NSMutableArray arrayWithArray:
[mutableArray1 subarrayWithRange:range]];
//Now apply search logic on your mutableArray2
for (int i=0;i<[mutableArray2 count];i++)
{
if ([[mutableArray2 objectAtIndex:i] isEqualToString:matchString])
{
//String matched
}
}
Hope this helps you!

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

find element inside array of dictionaries for a given value

I have two NSArray variables, each one of then gets a similar NSDictionary inside.
For a given row (indexPath.row):
NSArray* array1 = ...;
NSDictionary* item = [array1 objectAtIndex:indexPath.row];
int myid = [[item valueForKey:#"id"] intValue];
// id = 5
Now I need to find the element with id = 5 in array2, but because I'm a c# developer, I think it is a little weird to use a for to do that.
Is there any alternatives to a for?
NSArray has a method indexOfObjectPassingTest which you can use:
NSArray *array2 = ...;
int searchId = ...;
NSUInteger index2 = [array2 indexOfObjectPassingTest:^BOOL(NSDictionary *item, NSUInteger idx, BOOL *stop) {
BOOL found = [[item objectForKey:#"id"] intValue] == searchId;
return found;
}];
if (index2 != NSNotFound) {
// First matching item at index2.
} else {
// No matching item found.
}
This returns the first matching index. If you need all matching indexes, use indexesOfObjectsPassingTest.