iOS:How to separate particular string element in array? - ios

I got following response from server:
[{"bp":"000/000","dateTime":"05/12/2016 01:02:59 PM","doc":{"email_id":"batra#gmail.com","exception":0,"gender":"Male","id":0,"mobile_no":8055621745,"name":"Batra","profile_id":0,"qualification":"MD(Doctor)","reg_id":157,"salutation":"Mr","wellness_id":"251215782521"},"follow_up":"17","id":37,"medicine":["Syrup,Decold Total,20,0-0-1,Before Meal,1","Injection,Insulin,1,0-0-1,Before Meal,1","no","no","no","no","no","no","no","no"],"patient":{"email_id":"bishtrohit1989#gmail.com","exception":0,"gender":"Male","id":0,"mobile_no":8055621745,"name":"Rohit","profile_id":0,"qualification":"","reg_id":150,"salutation":"Mr","wellness_id":"290119935030"},"weight":"000"}]
From that I have separate the medicine array like following way:
NSMutableArray *Myarray = [NSMutableArray new];
for (int i=0; i<_menuItems.count; i++) {
[Myarray addObject:[[_menuItems objectAtIndex:i] objectForKey:#"medicine"]];
NSLog(#"medicine: %#",Myarray);
I got output for this as like:
medicine: (
(
"Syrup,Decold Total,20,0-0-1,Before Meal,1",
"Injection,Insulin,1,0-0-1,Before Meal,1",
no,
no,
no,
no,
no,
no,
no,
no
)
)
Now what i want:
1) remove that all noelement.
2) after that, i want only 2nd element in each string.
in short i want my final output is like:
[Decold Total, Insulin];
But i don't know how to do that..??
Please anyone can solve my issue. help will be appreciable.

You need to use NSPredicate on Myarray and filter it.
Make your Myarray like this.
NSMutableArray *Myarray = [NSMutableArray new];
for (int i=0; i<_menuItems.count; i++) {
[Myarray addObjectsFromArray:[[_menuItems objectAtIndex:i] objectForKey:#"medicine"]];
}
1) Remove that all no element.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"NOT (SELF = %#)",#"no"];
NSArray *filterArray = [Myarray filteredArrayUsingPredicate:predicate];
2) Want only 2nd element in each string
NSMutableArray *medicineArray = [[NSMutableArray alloc] init];
for (NSString* medicine in filterArray) {
NSArray *arr = [medicine componentsSeparatedByString:#","];
if (arr.count >= 2) {
[medicineArray addObject:[arr objectAtIndex:1]];
}
}

Related

Filter NSMutableArray on the base of filtering another NSMutableArray

I have 3 NSMutableArrays of identical size. They are "linked" that means that for the corresponding index they have something related to each other.
tableData = [NSMutableArray arrayWithObjects:#"Egg Benedict", #"Mushroom Risotto", #"Full Breakfast", nil]
thumbnails = [NSMutableArray arrayWithObjects:#"egg_benedict.jpg", #"mushroom_risotto.jpg", #"full_breakfast.jpg",nil]
prepTime = [NSMutableArray arrayWithObjects:#"10min", #"15min", #"8min",nil]
This comes from a tutorial I'm playing on.
I'm filtering the tableData array like this:
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"SELF contains[cd] %#",
searchText];
searchResultsData = [[tableData filteredArrayUsingPredicate:resultPredicate] mutableCopy];
where searchText is the string containing the filter (for example "egg").
This works great, I mean I have the correct filtering. (searchResultsData is another NSMutableArray)
What I need to do is filter the other two NSMutableArrays on the basis of the result got from the NSPredicate above.
So I created other two NSMutableArrays called "searchResultThumbnails" and "searchResultPrepTime".
I'm expecting this: if I filter using the word "egg" I want the first element containing "egg" from the "tableData" array (in this case only one element) and the correspondent element at index in the thumbnails and preptime arrays.
So after filtering with "Egg" the result should be:
searchResultData = "Egg"
searchResultThumbnails = "egg_benedict.jpg"
searchResultPrepTime = "10min"
Thank you for your help.
Believing "They are "linked" that means that for the corresponding index they have something related to each other." as your situation
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"SELF contains[cd] %#",
searchText];
searchResultsData = [[tableData filteredArrayUsingPredicate:resultPredicate] mutableCopy];
NSString *searchedText = [searchResultsData objectAtIndex:0];
NSInteger index = [tableData indexOfObject:searchedText]; //if searchedText = "Egg"
NSString *thumb = [thumbnails objectAtIndex:index];
NSString *prep= [prepTime objectAtIndex:index];
But this is not a better way to do this.
You got couple of options like
You can use a custom Class which might have properties item, thumbnail, prepTime.
You can also use a Array of dictionaries similar to the following format,
array = (
{
searchResultData = "Egg"
searchResultThumbnails = "egg_benedict.jpg"
searchResultPrepTime = "10min"
}
{
searchResultData = "someItem"
searchResultThumbnails = "some.jpg"
searchResultPrepTime = "10min"
}
)
Try this:
NSArray* tableData = [NSMutableArray arrayWithObjects:#"Egg Benedict", #"Mushroom Risotto", #"Full Breakfast", nil];
NSArray* thumbnails = [NSMutableArray arrayWithObjects:#"egg_benedict.jpg", #"mushroom_risotto.jpg", #"full_breakfast.jpg",nil];
NSArray* prepTime = [NSMutableArray arrayWithObjects:#"10min", #"15min", #"8min",nil];
NSMutableArray *storedIndex = [NSMutableArray arrayWithCapacity:tableData.count];
for (NSUInteger i = 0 ; i != tableData.count ; i++) {
[storedIndex addObject:[NSNumber numberWithInteger:i]];
}
//Now you are going to sort tabledata.. with it we will sort storedIndexs
//suppose we will compare the strings for this time
[storedIndex sortUsingComparator:^NSComparisonResult(id obj1, id obj2){
NSString *lhs = [[tableData objectAtIndex:[obj1 intValue]] lowercaseString];
NSString *rhs = [[tableData objectAtIndex:[obj2 intValue]] lowercaseString];
return [lhs compare:rhs];
}]; //now storedIndex are sorted according to sorted tableData array
NSMutableArray *sortedTableData = [NSMutableArray arrayWithCapacity:tableData.count];
NSMutableArray *sortedThumbnail = [NSMutableArray arrayWithCapacity:tableData.count];
NSMutableArray *sortedPrepTime = [NSMutableArray arrayWithCapacity:tableData.count];
[p enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSUInteger pos = [obj intValue];
[sortedTableData addObject:[tableData objectAtIndex:pos]];
[sortedThumbnail addObject:[thumbnails objectAtIndex:pos]];
[sortedPrepTime addObject:[prepTime objectAtIndex:pos]];
}];
//Now all will be correct index relation to each other as previous
It will work perfectly.
Happy coding. :)

How to remove all dictionaries from NSMutableArray based on the value in the dictionary

I am developing one iPad application.I have one NSMutableArray and NSMutableDictionary .These both are changeable based on the data from the web service.I need to remove some dictionary from my NSMutableArray based on the NSMutableDictionary values. Here I explain the situation through one example:
testArray =[{ language :"ESP"},{language :"ENG"},{language :"ENG"},{language :"FRH"}];
From the test array i need to remove the all Dictionaries which have key value language :"ENG".
I've written code like this:
for(int i =0;i<testArray.count;i++){
NSString *lang = [NSString stringWithFormat:#"%#", [testArray[i] objectForKey:#"language"]];
if([lang isEqualToString:#"ENG"]){
[testArray removeObjectAtIndex:i];
}
}
But it is not working. I think the problem is when I remove the dictionary from at index the array count is also reducing so the loop is executing based on new array count. Some help me to rewrite the code for get exact answer?
This is my favorite way, it's fast, clear and correct.
NSMutableArray *itemsToRemove = [NSMutableArray array];
for (id item in theArray) {
if ([item shouldBeRemoved])// Condition to check the key pair Value
[itemsToRemove addObject:item];
}
[theArray removeObjectsInArray:itemsToRemove];
Try this.
NSMutableArray *arrTemp = [[NSMutableArray alloc]initwithArray:testArray];
for(int i =0;i<testArray.count;i++){
NSString *lang = [NSString stringWithFormat:#"%#", [testArray[i] objectForKey:#"language"]];
if([lang isEqualToString:#"ENG"]){
[arrTemp removeObjectAtIndex:i];
}
}
[testArray removeAllObjects];
testArray = arrTemp;
for(int i =0;i<testArray.count;i++){
NSString *lang = [NSString stringWithFormat:#"%#", [testArray[i] objectForKey:#"language"]];
if([lang isEqualToString:#"ENG"]){
[testArray removeObjectAtIndex:i];
i--;
}
}
Replace your code with below code.
NSMutableArray *arrTemp = [NSMutableArray new];
for(int i =0;i<testArray.count;i++){
NSString *lang = [NSString stringWithFormat:#"%#", [testArray[i] objectForKey:#"language"]];
if([lang isEqualToString:#"ENG"]){
[arrTemp addObject:[NSNumber numberWithInt:i]];
}
}
for(int k=0;k<[arrTemp count];k++)
{
int ii = [[arrTemp objectAtIndex:k]intValue];
[testArray removeObjectAtIndex:ii];
}
let me know it is working or not!!!
Happy Coding!!!
I would implement that using NSPredicate:
NSMutableArray *testArray = [#[#{ #"language" :#"ESP"}, #{#"language" :#"ENG"},
#{#"language" :#"ENG"}, #{#"language" :#"FRH"}] mutableCopy];
NSPredicate *predicate =
[NSPredicate predicateWithFormat:#"language != %#", #"ENG" ];
testArray = [[testArray filteredArrayUsingPredicate:predicate] mutableCopy];
I have just tested it, it works (it is short and nice to read, but NSPredicate can be really slow).
Another way to do it is using enumerateObjectsWithOptions:usingBlock:
[testArray enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSDictionary *dict, NSUInteger index, BOOL *stop) {
if ([dict[#"language"] isEqualToString:#"ENG"]) {
[testArray removeObjectAtIndex:index];
}
}];
Pleace notice that i use NSEnumerationReverse as NSEnumerationOptions because according to docs of removeObjectAtIndex:- Method :
To fill the gap, all elements beyond index are moved by subtracting 1
from their index.

Adding objects to dictionary in a loop overwrites previous values

I have three NSArrays, and I want to combine them all into a single NSDictionary. The problem is that as I iterate through the arrays and create the dictionary, it overwrites the previous object. In the end I only have one object in my dictionary. What am I doing wrong? Here's my code:
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
for(int i=0; i<[array0 count]; i++) {
[dict setObject:[array0 objectAtIndex:i]
forKey:#"one"];
[dict setObject:[array1 objectAtIndex:i] f
orKey:#"two"];
[dict setObject:[array2 objectAtIndex:i]
forKey:#"three"];
}
Maybe this will clarify what I mean...
this is the result I'm going for:
{one = array0_obj0, two = array1_obj0, three = array2_obj0},
{one = array0_obj1, two = array1_obj1, three = array2_obj1},
{one = array0_obj2, two = array1_obj2, three = array2_obj2},
etc
Thanks
Issue
You are inserting and replacing the same object at the specific key. So all what dictionary has is its last object at the last index.
Solution
Use this code to add the three arrays into one dictionary with your specific keys.
NSDictionary *yourDictinary = #{#"one": array0, #"two": array1, #"three": array3};
Edit
If you need to add objects of your NSMutableArrays to one NSDictionary you can follow the answer posted by #ElJay, but that's not a good practice, since you are dealing with multiple objects with unique keys.
Update
To do that thing, we are talking about a single NSMutableArray and multiple NSDictinarys.
Follow this code:
NSMutableArray *allObjects = [NSMutableArray new];
for(int i=0; i<[array0 count]; i++) {
dict = #{#"one": array0[i], #"two": array1[i], #"three": array2[i]};
[allObjects addObject:dict];
}
Here ya go:
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
for(int i=0; i<[array0 count]; i++) {
[dict setObject:[array0 objectAtIndex:i] forKey:[NSString stringWithFormat:#"arr0_%d", i]];
[dict setObject:[array1 objectAtIndex:i] forKey:[NSString stringWithFormat:#"arr1_%d", i]];
[dict setObject:[array2 objectAtIndex:i] forKey:[NSString stringWithFormat:#"arr2_%d", i]];
}
Edit - with revised question:
self.array0 = #[#"Array0_0",#"Array0_1",#"Array0_2", #"Array0_3"];
self.array1 = #[#"Array1_0",#"Array1_1",#"Array1_2", #"Array1_3"];
self.array2 = #[#"Array2_0",#"Array2_1",#"Array2_2", #"Array2_3"];
NSMutableArray *finalArray = [[NSMutableArray alloc] init];
for (int i=0; i< [_array0 count]; i++) {
NSDictionary *dict = #{#"one":[_array0 objectAtIndex:i], #"two":[_array1 objectAtIndex:i],#"three":[_array2 objectAtIndex:i]};
[finalArray addObject:dict];
}
NSLog(#"finalArray = %#", [finalArray description]);
You're reusing the keys ("one", "two" and "three") through each iteration of the loop. Keys in an NSDictionary have to be unique.
If you want many dictionary but only three keys, you should save each dict in an array.

Want to get key value from NSDictionary

I want to get all key values in an array. Here I used the keyword allKeysForObject. While using allKeysForObject, I got value within parenthesis. I want to store value without parenthesis.
Here is my code:
dict = [[NSMutableDictionary alloc]init];
[dict setValue:#"Hai" forKey:#"1"];
[dict setValue:#"lrd" forKey:#"2"];
NSArray *keys = [dict allKeys];
NSMutableArray *countryArray = [[NSMutableArray alloc]init];
NSMutableArray *keyObjects = [[NSMutableArray alloc]init];
for(NSString* key in keys) {
NSString *obj = [dict objectForKey:key];
[countryArray addObject:obj];
}
for (int i =0; i < [countryArray count]; i++) {
[keyObjects addObject:[dict allKeysForObject: [countryArray objectAtIndex:i]]];
}
NSLog(#"%#",[keyObjects objectAtIndex:0]);
The NSLog value is:
2013-11-28 17:12:48.400 Help[6775:c07] (
1
)
Thanks in advance.
Replace:
NSLog(#"%#",[keyObjects objectAtIndex:0]);
With:
NSLog(#"%#",[keyObjects objectAtIndex:0][0]);
You are storing in keyObjects the value returned by allKeysForObject: which is a NSArray.
You will get all values in an NSDictionary using [dict allValues]. you dont need to manually iterate the array
dict = [[NSMutableDictionary alloc]init];
[dict setValue:#"Hai" forKey:#"1"];
[dict setValue:#"lrd" forKey:#"2"];
NSMutableArray *countryArray = [[dict allValues] mutableCopy];
NSMutableArray *keyObjects = [[NSMutableArray alloc]init];
for (int i =0; i < [countryArray count]; i++) {
[keyObjects addObject:[dict allKeysForObject: [countryArray objectAtIndex:i]]];
}
NSLog(#"%#",[keyObjects objectAtIndex:0][0]);
Instead of using loop for getting all key values from NSDictionary use - (NSArray *)allKeys;
method to do that. It is always good to use given methods than writing our own code to achieve the same.
so replace of the for loop with following code...
keyObjects = [[dict allKeys]mutableCopy]; // mutableCopy because I think you want it mutable as your array is mutable.
EDIT
AFA your code concern, your are getting parenthesis because you are storing all keys in keyObjects array as array, that why you can see those parenthesis out there in you log statement. and this is because allKeysForObject method returns array of keys related to given object.
and if you want it to be done in your way here it is...
for (int i =0; i < [countryArray count]; i++) {
[keyObjects addObject:[dict allKeysForObject: [[countryArray objectAtIndex:i]0]]];
}
While NSLog-ing:
Whenever you see (...) it is array.
Whenever you see {...} it is dictionary.
So in your case it is shown as (1) so this is an array with one object.
Hence you need to do through one level down to retrieve it.
NSLog(#"%#",[[keyObjects objectAtIndex:0] objectAtIndex:0]); //or
NSLog(#"%#",[keyObjects objectAtIndex:0][0]);

Optimizing query for search using nspredicates

This issue has been brought up a lot but I can't seem to optimize this piece of search code any further.
this filterSet array has about 1000 items and it's taking 8 seconds to reproduce results on a non-simulator iPad (simulator shows results in less than a second):
for(NSString *rowID in [self.filterSet array]) {
self.rowResults = [self.filteredResults filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"rowID = %#", rowID]];
self.rowResults = [self.rowResults valueForKey:#"value"];
self.duplicateValueSet = [NSOrderedSet orderedSetWithArray:self.rowResults];
filterCount = [[self.resultsArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF = %#", rowID]] count];
if([self.duplicateValueSet count] != filterCount)
filterCount -= abs([self.duplicateValueSet count] - filterCount);
if(filterCount == matchingCount)
[self.results addObject:rowID];
}
any suggestions to optimizing this query? The majority of the search is taken up in all the filters and predicate sorting. thanks.
edit: so i removed a lot of the code in the for loop and found the culprit to be the first line
self.rowResults = [self.filteredResults filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"rowID = %#", rowID]];
this is for some reason taking 7 seconds to execute. Is there a faster/more efficient way to create a predicate to match the rowID string? I've thought about using the makeobjectsperformselector NSArray method but for some reason I get the NSCFNumber unrecognized selector issue (which is saying my array has NSNumbers instead of NSStrings)
so my initial algorithm was running at O(N^2) which is pretty much as bad as it gets (realistically).
I've ended up using an NSDictionary to map keys/values so that I can easily reference them within the first for loop's first pass:
NSMutableDictionary *filteredResultsDict = [[[NSMutableDictionary alloc] init] autorelease];
for (int i = 0; i < [filteredResults count]; i++) {
NSString *key = [[filteredResults objectAtIndex:i] valueForKey:#"rowID"];
NSMutableArray *filtersArray = [NSMutableArray array];
NSMutableArray *tempArray = [filteredResultsDict objectForKey:key];
if (tempArray != nil || [tempArray count] > 0) {
[tempArray addObject:[filteredResults objectAtIndex:i]];
[filteredResultsDict setValue:tempArray forKey:key];
}
else {
[filtersArray addObject:[filteredResults objectAtIndex:i]];
[filteredResultsDict setValue:filtersArray forKey:key];
}
}
and then in my actual for loop, I can call this in place of the previous rowResults:
NSNumber *rowIDNum = [NSNumber numberWithInteger: [rowID integerValue]];
rowResults = [[filteredResultsDict objectForKey:rowIDNum] valueForKey:#"value"];

Resources