loop through array of dictionaries to find a value - objective-c

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

Related

checking whole boolean of NSMutableArray

I have an array that I am filling with boolean values in the following code.
for(int i = 0; i < 15; i++){
int checkVal = [(NSNumber *)[__diceValue objectAtIndex:i] intValue];
if(checkVal == matchVal){
[_diceMatch replaceObjectAtIndex:i withObject:[NSNumber numberWithBool:y]];
}
}
Whats the shortest way to write a conditional to check the array "_diceMatch" for all true values?
If your array can only contain the values "true" (#YES) or "false" (#NO)
then you can simply check for the absence of #NO:
if (![_diceMatch containsObject:#NO]) {
// all elements are "true"
}
NSUInteger numberOfTrueValues = 0;
for (NSNumber *value in _diceMatch) {
if ([value boolValue]) {
numberOfTrueValues++;
}
}
Shortest way? maybe not. Easiest way? Yes
- (BOOL)isDictMatchAllTrue {
for (NSNumber *n in _dictMatch) {
if (![n boolValue]) return NO;
}
return YES;
}
or you don't like writing loop
NSSet *set = [NSSet setWithArray:_diceMatch];
return set.count == 1 && [[set anyObject] boolValue];
Note: first version return YES when array is empty but second version return NO.
You can add
if (_dictMatch.count == 0) return YES; //or NO
to fix it.

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

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!

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.

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;