I have an NSArray of NSDictionary.
Each dictionary in the array has three keys: 'Name', 'Sex' and 'Age'
How can I find the index in NSArray of NSDictionary where, for example, Name = 'Roger'?
On iOS 4.0 and up you can do the following:
- (NSUInteger) indexOfObjectWithName: (NSString*) name inArray: (NSArray*) array
{
return [array indexOfObjectPassingTest:
^BOOL(id dictionary, NSUInteger idx, BOOL *stop) {
return [[dictionary objectForKey: #"Name"] isEqualToString: name];
}];
}
Elegant, no?
NSUInteger count = [array count];
for (NSUInteger index = 0; index < count; index++)
{
if ([[[array objectAtIndex: index] objectForKey: #"Name"] isEqualToString: #"Roger"])
{
return index;
}
}
return NSNotFound;
If you're using iOS > 3.0 you will be able to use the for in construct.
for(NSDictionary *dict in myArray) {
if([[dict objectForKey:#"Name"] isEqualToString:#"Roger"]) {
return [myArray indexForObject:dict];
}
}
There's method [NSArray indexOfObjectPassingTest]. But it employs blocks, an Apple extension to C, and therefore is evil. Instead, do this:
NSArray *a; //Comes from somewhere...
int i;
for(i=0;i<a.count;i++)
if([[[a objectAtIndex:i] objectForKey: #"Name"] compare: #"Roger"] == 0)
return i; //That's the index you're looking for
return -1; //Not found
Related
My Problem Scenario is like this. I have an NSMutableArray ( Every Object is Nsstring). I have a UItextField ( as Client said) for Search.
I want know how to Search String into NSMutableArray like this
if I type A into textfield only those Content come from NSMutableArray which start From A.
if I type AB into TextField only those Content Comes from NSMutableArray which is started from AB..
....
I am Trying NSRange Concept I like share Mycode
~
for (int i=0; i<[[localTotalArrayForAwailable objectForKey:#"PUNCH"] count]; i++)
{
NSString *drinkNamePuch= [[[localTotalArrayForAwailable objectForKey:#"PUNCH"] objectAtIndex:i] drinkNames];
NSRange titleResultsRange = [drinkNamePuch rangeOfString:searchText options:( NSCaseInsensitiveSearch)];
if (titleResultsRange.length>0)
{
[searchArraypuch addObject:[[localTotalArrayForAwailable objectForKey:#"PUNCH"] objectAtIndex:i]];
[copyListOfItems setValue:searchArraypuch forKey:#"PUNCH"];
}
}
~
Based on this code search not working proper as i need.
Thanks
If you're trying to find all of the strings that match your searchText from the beginning, then you should check:
if ( titleresultsRange.location == 0 )
Other than that, I am not sure what is "not working proper", you need to provide a better explanation of what your expected results are, and what your actual results are.
Do this;
NSPredicate* predicate = [NSPredicate predicateWithFormat:#"SELF BEGINSWITH[cd] %#", searchText];
NSArray* filteredStrings = [[localTotalArrayForAwailable objectForKey:#"PUNCH"] filteredArrayUsingPredicate:predicate];
In filteredStrings you got all the strings that begins with searchText.
You might find Predicate Programming Guide helpful.
try this logic....it is working
NSMutableArray *arr = [[NSMutableArray alloc]initWithObjects:#"aa",#"bbb",#"bb",#"cc",#"dd",#"ee",#"ff",#"gg",#"hh",#"ii", nil];
NSMutableArray *arrNew = [[NSMutableArray alloc]init];
NSString *strSearch = #"cccc";
int k = strSearch.length;
for (int i=0; i<[arr count]; i++) {
for (int j=0; j<k; j++) {
if (k<=[[arr objectAtIndex:i] length]) {
if ([strSearch characterAtIndex:j] != [[arr objectAtIndex:i]characterAtIndex:j]) {
break;
}
else if(j == k-1){
[arrNew addObject:[arr objectAtIndex:i]];
}
}
}
}
NSLog(#"%#",[arrNew description]);
You can use these methods, which are provided by NSArray/NSMutableArray:
In NSArray see section "Finding Objects in an Array" for filtering methods starting with "indexesOfObjects...", e.g. indexesOfObjectsPassingTest:
In NSArray see section "Deriving New Arrays" for the method filteredArrayUsingPredicate:
In NSMutableArray there is a method filterUsingPredicate:
For narrowing the results you can continue applying the filtering consecutively to the filtered arrays or index sets.
Example with indexesOfObjectsPassingTest: using a block:
NSArray *strings = [NSArray arrayWithObjects:#"A", #"a", #"aB", #"AbC", #"Bag", #"Babc", #"baCK", #"", #"dba", nil];
NSString *searchString = #"Ab";
BOOL (^startsWithPredicate)(id, NSUInteger, BOOL*) = ^BOOL (id obj, NSUInteger idx, BOOL *stop) {
NSString *string = (NSString *) obj;
NSRange range = [string rangeOfString:searchString options:NSCaseInsensitiveSearch];
return (range.location == 0);
};
NSIndexSet *indexSet = [strings indexesOfObjectsPassingTest:startsWithPredicate];
NSLog(#"Strings found: %#", [strings objectsAtIndexes:indexSet]);
Output:
Strings found: (
aB,
AbC
)
NSMutableArray*array = [[NSMutableArray alloc]init];
NSArray*Somearray = [NSArray arrayWithObjects:1st Object,2ndObject,3rd Object,4th object,5th Object,nil];
In the above array 1st Object,2ndObject,3rd Object,4th object,5th Object having val,content,conclusion in each index.
for(int i=0;i<[Somearray count];i++)
{
______________
Here the code is there to give each index ,that is having val,content,conclusion ..
After that val,content,conclusion in each index will be add to Dict..
____________
NSDictionary *Dict = [NSDictionary dictionaryWithObjectsAndKeys:val,#"val",content,#"content",conclusion,#"conclusion",nil];
//Each time adding dictionary into array;
[array addObject:Dict];
}
The above Dictionary is in for loop and the keyvalue pairs will be add 5 times(Somearray Count).Now array is having in
array = [{val="1.1 this is first one",content="This is the content of 0th index",conclusion="this is the conclusion of 0th index"},{val="1.2 this is first one",content="This is the content of 1st index",conclusion="this is the conclusion of 1st index"},____,____,______,{val="1.5 this is first one",content="This is the content of 4th index",conclusion="this is the conclusion of 4th index"},nil];
Now i am having NSString*string = #"1.5";
Now i need the index where val is having 1.5 in it.How to send the str in to array to find the the index.
Can anyone share the code please.
Thanks in advance.
Use method indexOfObject
int inx= [array indexOfObject:#"1.5"];
For Find index particular key value.
int inx;
for (int i=0; i<[array count]; i++) {
if ([[[array objectAtIndex:i] allKeys] containsObject:#"val"]) {
inx=i;
break;
}
}
The method you are looking for is -[NSArray indexOfObjectPassingTest:]. You would use it like this:
NSUInteger i = [array indexOfObjectPassingTest:^(id obj, NSUInteger idx, BOOL *stop) {
return [[id objectForKey:#"val"] rangeOfString:#"1.5"].location != NSNotFound;
}];
If you just want to check that val starts with "1.5" you would use hasPrefix: instead.
Try this -
NSArray *valArray = [array valueForKey:#"val"];
int index = [valArray indexOfObject:#"1.5"];
Appended answer given by Mandeep, to show you the magic of key value coding ;)
NSUInteger idx = UINT_MAX;
NSCharacterSet* spaceSet = [NSCharacterSet whitespaceCharacterSet];
for(int i=0,i_l=[Yourarray count];i<i_l;i++) {
NSString* s_prime = [[Yourarray objectAtIndex:i] valueForKey:#"val"];
if ([s_prime length] < 4) {
continue;
}
NSString *subString = [[s_prime substringToIndex:4] stringByTrimmingCharactersInSet:spaceSet];
// NSLog(#"index %#",s);
if ([subString isEqualToString:secretNumber]){
idx = i;
break;
}
}
if (idx != UINT_MAX) {
// NSLog(#"Found at index: %d",idx);
} else {
// NSLog(#"Not found");
}
Now I'm trying the following and it works.
- (void)findDictionaryWithValueForKey:(NSString *)name {
for (NSDictionary * set in myArray) {
if ([[set objectForKey:#"title"] isEqualToString:name])
\\do something
}
}
EDIT:
I've added one extra argument to the post of bshirley. Now it looks more flexible.
- (NSDictionary *)findDictionaryWithValue:(NSString*)name forKey:(NSString *)key {
__block BOOL found = NO;
__block NSDictionary *dict = nil;
[self.cardSetsArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
dict = (NSDictionary *)obj;
NSString *title = [dict valueForKey:key];
if ([title isEqualToString:name]) {
found = YES;
*stop = YES;
}
}];
if (found) {
return dict;
} else {
return nil;
}
}
Here's one possible implementation using newer API. (I also modified the method to actually return the value). Provided mostly to demonstrate that API. The assumption is that the title is unique to one dictionary within your array.
- (NSDictionary *)findDictionaryWithValueForKey:(NSString *)name {
// ivar: NSArray *myArray;
__block BOOL found = NO;
__block NSDictionary *dict = nil;
[myArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
dict = (NSDictionary *)obj;
NSString *title = [dict valueForKey:#"title"];
if ([title isEqualToString:name]) {
found = YES;
*stop = YES;
}
}];
if (found) {
return dict;
} else {
return nil;
}
}
Use filteredArrayUsingPredicate: method of the array to get all the dictionaries that satisfy your requirement.
NSPredicate * predicate = [NSPredicate predicateWithFormat:#" title MATCHES[cd] %#", name];
NSArray * matches = [myArray filteredArrayUsingPredicate:predicate];
Now matches is the array of dictionaries that have the title key equal to name.
- (void)findDictionaryWithValueForKey:(NSString)name {
for (NSDictionary * set in myArray) {
NSString *s=[NSString stringWithFormat:#"%#",[set objectForKey:#"title"]];
if ([s isEqualToString:name])
\\do something
}
OR
if (s == name])
\\do something
}
}
I will also suggest this way,it would be better if you use a break statement,
- (void)findDictionaryWithValueForKey:(NSString)name {
for (NSDictionary * set in myArray) {
if ([[set objectForKey:#"title"] isEqualToString:name])
\\do something
break;
}
}
As per the NSArray documentation,
valueForKey:
Returns an array containing the results of invoking valueForKey: using key on each of the array's objects.
- (id)valueForKey:(NSString *)key
Parameters
key
The key to retrieve.
Return Value
The value of the retrieved key.
Discussion
The returned array contains NSNull elements for each object that returns nil.
Availability
* Available in Mac OS X v10.3 and later.
EDIT:
try this,
[myArray valueForKey:#"name"];
//this will return array of values, but this actually differ from what to want
I want to take the values from NSMutableArray but want to read from last index to 1st index
thank you
for (id someObject in [someArray reverseObjectEnumerator])
{
//do your thing
}
2 other options:
Simple for-loop (surely not recommended):
for (int i = [array count]-1; i >= 0; ++i)
id value = [array objectAtIndex: i];
Block-based enumeration:
[array enumerateObjectsWithOptions: NSEnumerationReverse
usingBlock: ^(id obj, NSUInteger idx, BOOL *stop){
//do something
}];
Mark's answer is useful, but this form may be useful when you want to mutate the array:
while ([arr count]) {
id obj = [arr lastObject];
// use obj
[arr removeLastObject];
}
Suppose I have an array having elements "am","john","rosa","freedom". I want to compare these elements and result would be the word and the size of the longest word. I am using objective C.
There isn't a "built-in" way of doing this, however you can use NSArray's sortedArrayUsingSelector: and create a category on NSString to provide a lengthCompare: method.
// NSString+LengthCompare.h
#import NSString.h
#interface NSString (LengthComparison)
- (NSComparisonResult)lengthCompare:(NSString *)aString;
#end
// NSString+LengthCompare.m
#import NSString+LengthCompare.h
#implememtation NSString (LengthComparison)
- (NSComparisonResult)lengthCompare:(NSString *)aString
{
if ([self length] < [aString length]) {
return NSOrderedAscending;
} else if ([self length] > [aString length]) {
return NSOrderedDescending;
} else {
return NSOrderedSame;
}
}
#end
Now you can sort an of strings in ascending order using lengthCompare:
NSArray *array = [NSArray arrayWithObjects: #"am", #"john", #"rosa", #"freedom", nil];
NSArray *arraySortedByStringLength = [array sortedArrayUsingSelector:#selector(lengthCompare:)];
NString *shortestWord = [[arraySortedByStringLength objectAtIndex:0] retain];
NSLog(#"shortest word, %# has length %d", shortestWord, [shortestWord length];
[shortestWord release];
NString *longestWord = [[arraySortedByStringLength lastObject] retain];
NSLog(#"Longest word, %# has length %d", longestWord, [longestWord length];
[longestWord release];
Sounds like a classical logic exercise or is it something I miss in your question ?
int longestWordIndex = 0;
NSUInteger longestWordSize = 0;
for (int i=0 ; i<[nameArray count] ; i++) {
NSString* element = (NSString*)[nameArray objectAtindex:i];
if([element lenght] > longestWordSize) {
longestWordSize = [element lenght];
longestWordIndex = i;
}
}
NSLog("Longest word is %# with size of :%d", [nameArray objectAtIndex:longestWordIndex], longestWordSize);
I'll add one more approach to the two above -- use a block to do the body of your iteration.
__block NSUInteger longestWordSize = -1; // Make sure at least one object will be longer.
__block NSUInteger longestWordIndex;
[nameArray enumerateObjectsUsingBlock:^(id currentWord, NSUInteger index, BOOL *stop) {
if ([currentWord length] > longestWordSize) {
longestWordSize = [currentWord length];
longestWordIndex = index;
}
}];
NSLog("Longest word is %# with size of :%d", [nameArray objectAtIndex:longestWordIndex], longestWordSize);
Edit: The max and index have to be of storage type __block so they can be changed from inside the block.