I have an array of NSDictionaries and i can access the values in them just fine but i am trying to filter these dictionaries down based on a user's search (user can only search by the dictionary key (#"uniqueSignName").
Once the user has searched through the names property i then need to display ALL dictionary associated data for that #"uniqueSignName" value.
I do the following code and always get the correct amount of NSLogs. For the life of me i cannot remember how to GET those dictionaries.
for (int i = 0; i < [filteredDictionaries count]; i++) {
if ([[[filteredDictionaries valueForKey:#"uniqueSignName"] objectAtIndex:i] isEqualToString:[self.filteredResults objectAtIndex:indexPath.row]]) {
NSLog(#"Power Rangers");
}
}
Eg: I search for "John"
NSLog: #"Power Rangers"
Correctly only appears once.
Now, how do i access another property of "John's" dictionary?
If you want to search the name then better way is that to use NPredicate without iterating the array.
Please see the below example..it may help you...
// Here array is your main array...
NSArray *filteredarray = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"(uniqueSignName == %#)", #"John"]];
So the problem is solved, I can now access all the filtered properties.
for (NSDictionary *dict in filteredDictionaries) {
if ([[self.filteredResults objectAtIndex:indexPath.row] isEqualToString: dict[#"uniqueSignName"]]) {
NSString *myString = [NSString stringWithFormat:#"%#", dict[#"pType"]];
NSLog(#"hugh: %#", myString);
myString = displayPtype;
}
}
Related
In my project i get response data in the form of
{
"procedures": [5950]
0: {
"Procedures": {
"id": "1"
"procedure_name": "3d render w/o postprocess"
"procedure_code": "76376"
}
}
1: {
"Procedures": {
"id": "2"
"procedure_name": "3d rendering w/postprocess"
"procedure_code": "76377"
}
there are 5950 elements in the data array. i create separate arrays for "id" and "Procedure_name" and show data in UITableView it displays correct data with id.
I also applied search functionality to filter data as it is so difficult to find any element in 5950 elements by scrolling.
search function is also works well but when i select any UITableViewCell of the filtered result it doesn't provide the actual id of that element whereas it returns the current indexpath value of the UITableView.
for searching i put the following code
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
tempArray = [NSArray arrayWithArray:dataArray];
NSString *stringToSearch = textField.text;
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF BEGINSWITH[c] %#",stringToSearch]; // if you need case sensitive search avoid '[c]' in the predicate
NSArray *tempresults = [dataArray filteredArrayUsingPredicate:predicate];
if (tempresults.count > 0)
{
tempArray = [NSArray arrayWithArray:tempresults];
}
[searchdiagtable reloadData];
return YES;
}
in DidSelectRow method i apply the following code
if (tableView == searchdiagtable)
{
UITableViewCell *selectedCell = [searchdiagtable cellForRowAtIndexPath:indexPath];
NSLog(#"%#", selectedCell.textLabel.text);
searchdiag. text = selectedCell.textLabel.text;
searchResultId = [iddict objectAtIndex:indexPath.row]; // iddict is the array where i store the values of "id" from dictionary.
[searchdiagtable deselectRowAtIndexPath:indexPath animated:YES];
searchdiagtable.hidden = YES;
}
checking on your question which I can get is issue must be using a wrong array iddict for search as it looks to me its should be tempArray
searchResultId = [iddict objectAtIndex:indexPath.row];
This line of code creates the problem, tableView reuses cells.
if you selected the cell , it selects the cell index (0, 1, 2 ... etc). So your array returns the first values.
If you are not displaying the "Id" in your table view. You cant get correct id from your array.
There is one solution for this,save id and name in a single dictionary,
like:{
"id":"name"
}
using the name you can get the id from dictionary.
hey you already get two arrays , one for ids and one for names.
How you do that..after response may be you did like this
NSMutableArray *id;
NSMutableArray *name;
for( ------ ){
[id addObject:[dict objectforkey:#"id"];
[name addObjec:[dict objectForKey:#"procedure_name"];
}
dict is reponse dictionary.
This is the way how you get arrays.now for dictionary
NSMutableDictionary *dict1 = [[NSMutableDictionary alloc]init];
for(){
[dict setObject:[dict objectforkey:#"id"] forKey:[dict objectForKey:#"procedure_name"];
}
just check the for loop carefully in your code..
i just get an easy way to create A:B type dictionary
i am sharing my code i used and works perfectly for me
NSDictionary * searchdict = [NSDictionary dictionaryWithObjects:dataArray forKeys:iddict];
NSLog(#"dict formed by combining %#",searchdict);
where dataarray and iddict are two arrays
it gives output dictionary as
1034 = "Catheterize for urine spec";
1035 = "Cauterization of cervix";
1036 = "CBC without platelet";
1037 = "CBC/diffwbc w/o platelet";
1038 = "Cbt 1st hour";
1039 = "Cbt each addl hour";
104 = "Amino acids quan 6 or more";
1040 = "Ccp antibody"; ......
yaa, I know we can directly add two arrays to dictionary. But it takes memory for two arrays and dictionary also.. so instead of creating two arrays.you can directly add it to dictionary. But what you did is also correct. In mobile applications every time we have to think about memory management also..
As the title suggests, my .plist file is in this format - I don't know how to mark it up well for you to read. Stackoverflow doesn't understand the format.
root (array)
Item 0 - Dict
numberOfPerson String
recipeName String
recipeIngredients String
Item 1 -Dict
NumberOfPerson String
...
I have a textfield for user and user will enter a couple of strings.
I want to look for matches with input and recipeIngredients of each item.
And when it is found I want to go to that cell in my tableview which i implemented.
how can I accomplish this.
These are what I have tried so far
NSString *path = [[NSBundle mainBundle] pathForResource:#"recipes" ofType:#"plist"];
NSArray *arrayOfPlist = [[NSArray alloc] initWithContentsOfFile:path];
This turned out useless I can not use objectForKey
for (int i=0; i<2; i++) {
recipeIngredientsArray = [[arrayOfPlist objectAtIndex:i] objectForKey:#"recipeIngredients"];
}
This didn't help me either I can not maintain a good isequl method
Thanks for the help.
You have an array of dictionaries that you want to filter. Look at using indexesOfObjectsPassingTest:. Run this on the array and test the passed dictionary to check the value of the recipeIngredients value.
NSIndexSet *indexes = [arrayOfPlist indexesOfObjectsPassingTest:^BOOL (NSDictionary *obj, NSUInteger idx, BOOL *stop) {
return [obj[#"recipeIngredients"] rangeOfString:input options:NSCaseInsensitiveSearch].location != NSNotFound;
}];
Then you can use indexes to see if you have any matches and to display them. Or, you could just use filteredArrayUsingPredicate: to filter the array directly:
NSArray *results = [arrayOfPlist filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"recipeIngredients CONTAINS[cd] %#", input]];
and then show only the filtered results in the table view.
Trough my ios first app developpement i have to re-order an array containing dictionaires, parsed from a xml document, the purpose of re-ordering it is to send it to a function that build a collapsible, so it need a childCell index and a parentCell Index to print the strings of each child then pass to another parent. The problem is here : i'am able to fill my big array containing arrays of dictionaries, then i that array and do a loop to fill the childArray to contain multiple dictionaries, then i add this child array to my parent array, every thing seem to run but it gives me an empty array at the end. i put my code to show you how i tried to do this :
stories is the NSArray of dictionaries, childArray is the Array that should contain the dictionaries of stories, and parentArray is the Array that contains it all.
If someone who already did that can explain me were it goes wrong please it would be very much appreciated.
-(NSMutableArray *)orderChildsAndParents:(NSMutableArray *)fromArray
{
int varial = 0;
int catIndex = 0;
NSMutableArray *parentArray = [NSMutableArray array];
while(varial < [stories count])
{
NSString* cleanedString = [[[[stories objectAtIndex:varial] objectForKey:#"category"] componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]
componentsJoinedByString:#""];
if ([cleanedString isEqualToString:[category objectAtIndex:catIndex] ])
{
if (!childArray || !childArray.count)
childArray = [NSMutableArray array];
[childArray addObject:[stories objectAtIndex:varial]];
varial++;
}
else{
[parentArray addObject:childArray];
[childArray removeAllObjects];
catIndex++;
}
}
NSLog(#"%#", parentArray);
return parentArray;
}
- (NSString *) labelForCellAtChildIndex:(NSInteger) childIndex withinParentCellIndex:(NSInteger) parentIndex {
NSMutableArray *orderedArray = [self orderChildsAndParents:stories];
NSLog(#"format string %#", [[[orderedArray objectAtIndex:parentIndex] objectAtIndex:childIndex] objectForKey:#"name"]); // empty :8
return [[[orderedArray objectAtIndex:parentIndex] objectAtIndex:childIndex] objectForKey:#"name"];
}
Hope someone could help me with that :
I'm using a NSDictionary to fill a UITableView.
Its model is like [key:userID => value:userName].
The tableView is only filled with userName but when clicked, it has to send the userID related.
The problem comes when I want to filter the UITable. I only found the way to filter a Dictionary by transforming it into NSArray (using Predicate) but it make me loose the relation between userNames and userIDs.
A solution would be to filter the initial NSDictionary to get a filtered NSDictionary (with still the relational key/value), but I don't know how to do that. I only found solutions to get Arrays.
How could I do that, or is there a better solution to do it?
There is a much better solution, François.
Create, from your NSDictionary (I will call it here myDictionary), an NSArray like this (declare it in your interface file):
NSArray *arrayForTableView;
Then, just after you load your NSDictionary, do the following:
arrayForTableView = [myDictionary allKeys]; // so you will have an array of all UserID's
Now, in your tableView: cellForRowAtIndexPath: method, you can do it like this:
cell.textLabel.text = [myDictionary objectForKey:[arraForTableView objectAtIndex:indexPath.row]];
And then, when you will want to pass the userID when the user selects the cell, in your tableView: didSelectRowAtIndexPath: you just do it this way:
id userIDSelected = [arraForTableView objectAtIndex:indexPath.row];
Then, when you want to filter the array according to the search, you can simply recreate your arrayForTableView, by "scanning" your NSDictionary this way:
NSString *typedString;
NSMutableArray *arrayFiltered = [NSMutableArray array];
for (int i = 0; i < [[myDictionary allKeys] count]; i++)
{
if ([[myDictionary objectForKey:[[myDictionary allKeys] objectAtIndex:i]] rangeOfString:typedString].location != NSNotFound)
{
[arrayFiltered addObject:[[myDictionary allKeys] objectAtIndex:i]];
}
}
arrayForTableView = arrayFiltered;
This way, you won't even need to change your UITableView dataSource and delegate methods.
You can do following to get value(userID) for selected key(userName) :
//iterate through whole dictionary
for(id key in yourNSDictionary)
{
// if key is the userName clicked
if([key isEqualToString:selectedUserName])
{
//userID for clicked userName
int userID = [yourNSDictionary objectForKey:#selectedUserName];
}
}
you're using an NSDictionary to populate an UITableView and this UITableView is only filled with the username which you get by doing
[dictionary objectForKey#"userID"];
a NSDictionary has two functions allkeys and allValues
NSArray* allUserID = [dictionary allKeys];
NSArray* allUserNames = [dictionary allValues];
this is a parallel arrays so that the index of one array, runs parallel with it's associated array.
Each cell of the table cell could also be a custom class that holds a reference to it's own id and username, this will allow you to only pass the cell and have it's data.
you can read about those functions in the NSDictionary documentation
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/Reference/Reference.html
i would recommend creating an NSArray or NSMutableArray with NSDictionary values - UITableViews are meant to be driven by arrays, where the array index matches the row number. Then you can easily create a custom filter for the array of dictionaries which take into account your data structure. Your code might include parts of this sample code:
NSString *idKey = #"userId";
NSString *nameKey = #"userName";
NSArray *arr = #[
#{
idKey : #(24),
nameKey : #"Oil Can Henry"
},
#{
idKey : #(32),
nameKey : #"Doctor Eggman"
},
#{
idKey : #(523),
nameKey : #"Sparticus"
},
];
NSString *searchTerm = #"Spar";
NSArray *newArray = [arr filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
return [evaluatedObject[nameKey] hasPrefix:searchTerm];
}]];
Advantages:
a single data structure to represent all your data
inherent, deterministic ordering
support for NSPredicate filtering
I am familiar with getting a string count from a known array
int numberOfWords = [self.wordArray count];
but I have an unknown number of strings in an unknown number of arrays, all referenced by a dictionary. This works - good.
NSMutableDictionary *eqClasses = [[NSMutableDictionary alloc] init];
The arrays and strings are added at runtime (with help of this board):
NSMutableArray* array = [eqClasses objectForKey:wordPattern];
if(!array) {
// create new array and add to dictionary if wordPattern not found
array = [NSMutableArray array];
[eqClasses setObject:array forKey:wordPattern];
}
[array addObject:tempWordStr];
Now I need to iterate through the dictionary and get the array with the largest word count. Is there a way to scroll through all the arrays in the dictionary without using a key (I won't know all the word patterns as they are generated dynamically), AND once I find the array with the most words, get that array/value and key/wordpattern?
Well, there is a way to get all the keys within a dictionary:
NSArray *keyArray = [myDict allKeys];
And then you just go through the array and get the object for each key.
A fast enumeration should work nicely.
for (NSString *string in NSArray){
...
} //Assuming your keys are strings!
You can save each string to a temporary string, and when encountering a new string, compare to find the longer one. If it's longer, replace the old string with the longer one.
Hope this helped! ^_^
^_^
Okay, so now that you have an array full of all the keys in the dictionary,
you can iterate through the entire array and get the corresponding value (the string) for each key.
NSArray *keyArray = [myDict allKeys]; //This gets all the keys
NSString *tempString = #""; //This is the string you will save the longest string in. It gets updated when a longer string is found in the following loop.
for (NSString *string in keyArray){
NSString *stringFromCurrentKey = [myDict objectForKey:string];
if(stringFromCurrentKey.length > tempString.length){
tempString = stringFromCurrentKey;
}
} //By the end, you should be left with the longest string contained in tempString!
^_^ Hope this made sense and helped!
Try this code:
NSArray *largestArray = nil;
for (NSString *key in dictionary)
{
NSArray *array = [dictionary objectForKey:key];
if (array.count > largestArray.count) // largestArray.count is 0 if largestArray is nil
{
largestArray = array;
}
}