Remove objects using NSPredicate - iphone

I have the folloving dictionary which has many sub dictionaries.
How can I remove objects where isChanged = 1 from parent dictionary using NSPredicate?
{
"0_496447097042228" = {
cellHeight = 437;
isChanged = 1;
};
"100000019882803_193629104095337" = {
cellHeight = 145;
isChanged = 0;
};
"100002140902243_561833243831980" = {
cellHeight = 114;
isChanged = 1;
};
"100004324964792_129813607172804" = {
cellHeight = 112;
isChanged = 0;
};
"100004324964792_129818217172343" = {
cellHeight = 127;
isChanged = 0;
};
"100004324964792_129835247170640" = {
cellHeight = 127;
isChanged = 1;
};
}

As a simple alternative to using NSPredicate, you can use the NSDictionary's built in keysOfEntriesPassingTest: This answer assumes "isChanged" is an NSString and the value 0 or 1 is an NSNumber:
NSSet *theSet = [dict keysOfEntriesPassingTest:^(id key, id obj, BOOL *stop) {
return [obj[#"isChanged"] isEqualToNumber: #1];
}];
The returned set is a list of keys that pass the test. From there, you could remove all that matched with:
[dict removeObjectsForKeys:[theSet allObjects]];

I solved my problem in the following way:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"isChanged == %d", 1];
NSArray *allObjs = [parentDict.allValues filteredArrayUsingPredicate:predicate];
[allObjs enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSMutableArray *keys = [[NSMutableArray alloc] initWithCapacity:0];
[keys setArray:[parentDict allKeysForObject:obj]];
[parentDict removeObjectsForKeys:keys];
[keys release];
}];

when you have array of dictionary than you can remove selected category's data using NSPredicate
here is code
NSString *selectedCategory = #"1";
//filter array by category using predicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"isChanged == %#", selectedCategory];
NSArray *filteredArray = [yourAry filteredArrayUsingPredicate:predicate];
[yourAry removeObject:[filteredArray objectAtIndex:0]];
But in your problem data is not in array it is in dictionary
your data should be in this format
(
{
cellHeight = 437;
isChanged = 1;
},
{
cellHeight = 145;
isChanged = 0;
},
{
cellHeight = 114;
isChanged = 1;
}
)

Related

search the values in array in iPhone sdk

I have the array like:
(
{
id=1;
Title="AAAA";
period_id=1;
},
{
id=2;
Title="BBBB";
period_id=2;
},
{
id=3;
Title="CCCC";
period_id=2;
},
{
id=4;
Title="DDDD";
period_id=2;
},
{
id=5;
Title="EEEE";
period_id=3;
},
)
Question: How can i know that Period_id=2 is multiple times in the array?
Help me solve this.
Thank you,
There are lots of ways to do so, Some of them are here ..
A:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"period_id == %#", #"2"];
NSArray *newArray = [array filteredArrayUsingPredicate:predicate];
NSLog(#"%d", [newArray count]);
B:
NSMutableArray *newArray = [[NSMutableArray alloc] init];
for (id obj in array)
{
if([obj[#"period_id"] isEqualToString:#"2"]){
[newArray addObject:obj];
}
}
NSLog(#"%d", [newArray count]);
C:
NSArray *allIds = [array valueForKey:#"period_id"];
NSCountedSet *set = [[NSCountedSet alloc] initWithArray:allIds];
for (id item in set)
{
NSLog(#"period_id=%#, Count=%d", item,[set countForObject:item]);
}
D:
NSArray *allIds = [array valueForKey:#"period_id"];
__block NSMutableArray *newArray = [[NSMutableArray alloc] init];
NSString *valueToCheck = #"2";
[allIds enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if([obj isEqualToString:valueToCheck])
[newArray addObject:obj];
}];
NSLog(#"%d", [newArray count]);
E:
NSIndexSet *indexes = [array indexesOfObjectsPassingTest:^(id obj, NSUInteger idx, BOOL *stop) {
return [[obj objectForKey:#"period_id"] isEqualToString:#"2"];
}];
NSArray *newArray = [array objectsAtIndexes:indexes];
NSLog(#"%d", [newArray count]);
try like this,
NSIndexSet *indices = [questionSections indexesOfObjectsPassingTest:^(id obj, NSUInteger idx, BOOL *stop) {
return [[obj objectForKey:#"period_id"] isEqualToString:#"2"];
}];
NSArray *filtered = [questionSections objectsAtIndexes:indices];
NSLog(#"duplictae:%d\n %#",[indices count],filtered);
O/P:-
duplicate: 3
(
{
name = bbbb;
"period_id" = 2;
},
{
name = ccccc;
"period_id" = 2;
},
{
name = ddddd;
"period_id" = 2;
}
)
if the array is sorted, as it seems at your case, just check if the next item has the same value as this one
for(int i = 0; i < array.size() - 1; i++) {
if (array[i].id == array[i + 1].id) {
// Duplicate
}
}
if you just want to know about id = 2
int idCount = 0;
for(int i = 0; i < array.size() - 1; i++) {
if (array[i].id == 2) {
idCount++;
}
}
if you also want to know the location
int idCount = 0;
int idarr[array.size()];
for(int i = 0; i < array.size() - 1; i++) {
if (array[i].id == 2) {
idarr[idCount++] = i;
}
}
I think this is a JSON response from what I gather. Yes you can get the period_id. Add all the period_id's in an NSMutableArray.
Then simply search for the period_id from within this array for the values of the period_id to be same . You will get the index on which the period_id's are same.
NSSet *uniqueElements = [NSSet setWithArray:myArray];
for(id element in uniqueElements) {
// iterate here
}
You could also use NSPredicate to check duplicate.
Try this Example:
NSPredicate *testPredicate = [NSPredicate predicateWithFormat:#"period_id.intValue == %d",value];
NSMutableArray *data = [[NSMutableArray alloc] init];
NSArray *testArray= [yourArray filteredArrayUsingPredicate:testPredicate];
NSLog(#"duplicate:%d",[testArray count]);

How to extract specific data has equal value for some key from NSDictionary into a combined NSArray

Right now i have a dictionary like this, it's just a example, i got A to Z:
(
{
id = 13;
name = "Roll";
firstLetter = R;
},
{
id = 14;
name = "Scroll";
firstLetter = S;
},
{
id = 16;
name = "Rock";
firstLetter = R;
},
{
id = 17;
name = "Start";
firstLetter = S;
}
)
I want to extract the dict has the same firstLetter and combine these into a NSArray object. The expected results like this:
R array:
(
{
id = 13;
name = "Roll";
firstLetter = R;
},
{
id = 16;
name = "Rock";
firstLetter = R;
}
)
and S array:
(
{
id = 14;
name = "Scroll";
firstLetter = S;
},
{
id = 17;
name = "Start";
firstLetter = S;
}
)
How to do that?
I believe the better method would be the one suggested by Saohooou
But it can be optimised as
NSArray *array = #[#{#"id": #13,#"name":#"Roll",#"firstLetter":#"R"},
#{#"id": #14,#"name":#"Scroll",#"firstLetter":#"S"},
#{#"id": #15,#"name":#"Rock",#"firstLetter":#"R"},
#{#"id": #16,#"name":#"Start",#"firstLetter":#"S"}];
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
[array enumerateObjectsUsingBlock:^(NSDictionary *dict, NSUInteger idx, BOOL *stop) {
NSString *key = dict[#"firstLetter"];
NSMutableArray *tempArray = dictionary[key];
if (!tempArray) {
tempArray = [NSMutableArray array];
}
[tempArray addObject:dict];
dictionary[key] = tempArray;
}];
NSLog(#"%#",dictionary);
NSMutableDictionay *dic = [NSMutableDictionay dictionay];
for ( YourObject *obj in yourDic.allValues )
{
NSMutableArray *dateArray = dic[obj.firstLetter];
if ( !dateArray )
{
dateArray = [NSMutableArray array];
[dic setObject:dateArray forKey:obj.firstLetter];
}
[dateArray addObject:obj];
}
so dic is what you want
I assume you organized the dict as an NSArray.
NSMutableDictionary* result = [NSMutableDictionary dictionary]; // NSDictionary of NSArray
for (id entry in dict) {
NSString* firstLetter = [entry firstLetter];
// Find the group of firstLetter
NSMutableArray* group = result[firstLetter];
if (group == nil) {
// No such group --> create new a new one and add it to the result
group = [NSMutableArray array];
result[firstLetter] = group;
}
// Either group has existed, or has been just created
// Add the entry to it
[group addObject: entry];
}
result holds what you want.
try this
NSString *currentStr;
//this int is to detect currentStr
NSInteger i;
NSMutableArray* R_Array = [[NSMutableArray alloc] init];
NSMutableArray* S_Array = [[NSMutableArray alloc] init];
for (NSDictionary *myDict in MyDictArray){
NSString *tempStr = [myDict objectForKey:#"firstLetter"];
if(currentStr = nil && [currentStr isEqualToString:""]){
currentStr = tempStr;
if([currentStr isEqualToString:"R"] ){
[R_Array addObject:myDict];
i = 0;
}else{
[S_Array addObject:myDict];
i = 1;
}
}else{
if([currentStr isEqualToString:tempStr]){
(i=0)?[R_Array addObject:myDict]:[S_Array addObject:myDict];
}else{
(i=0)?[R_Array addObject:myDict]:[S_Array addObject:myDict];
}
}
}
Base on your dictionaries. There are only two type, so i just created two array and use if-else for solving the problem. if there are multy values, you can try switch-case to do it.
Lets do this
NSMutaleDictionary * speDict = [[NSMutableDictionary alloc] init];
for(i=0;i<26;i++){
switch (i){
case 0:
[speDict setObject:[NSMutableArray alloc] init] forKey:#"A"];
break;
case 1:
[speDict setObject:[NSMutableArray alloc] init] forKey:#"B"];
break;
Case 2:
[speDict setObject:[NSMutableArray alloc] init] forKey:#"C"];
break;
...........
Case 25:
[speDict setObject:[NSMutableArray alloc] init] forKey:#"Z"];
break;
}
}
for (NSDictionary *myDict in MyDictArray){
NSString *tempStr = [myDict objectForKey:#"firstLetter"];
switch (tempStr)
case A:
[self addToMySpeDictArrayWithObject:myDict andStr:temStr];
break;
case B:
[self addToMySpeDictArrayWithObject:myDict andStr:temStr];
break;
Case C:
[self addToMySpeDictArrayWithObject:myDict andStr:temStr];
break;
...........
Case Z:
[self addToMySpeDictArrayWithObject:myDict andStr:temStr];
break;
}
-(void)addToMySpeDictArrayWithObject:(NSDictionary*)_dict andStr:(NString*)_str
{
NSMutableArray *tempArray = [speDict objectForKey:_str];
[tempArray addObject:_dict];
}
then the speDict is like
A:
//all firstletter is A
myDict
myDict
myDict
B:
//all firstletter is B
myDict
myDict
.......
First of all the sample you've provided is an array of dicts (not a dict as the question notes). Now, the easiest way to query this array is by using an NSPredicate. Something like this perhaps:
NSArray *objects = ...; // The array with dicts
NSString *letter = #"S"; // The letter we want to pull out
NSPredicate *p = [NSPredicate predicateWithFormat:#"firstLetter == %#", letter];
NSArray *s = [objects filteredArrayUsingPredicate:p]; // All the 'S' dicts
If for some reason you need to group all of your objects without having to ask for a specific letter each time, you could try something like this:
// Grab all available firstLetters
NSSet *letters = [NSSet setWithArray:[objects valueForKey:#"firstLetter"]];
for (NSString *letter in letters)
{
NSPredicate *p = [NSPredicate predicateWithFormat:#"firstLetter == %#", letter];
NSArray *x = [objects filteredArrayUsingPredicate:p];
// Do something with 'x'
// For example append it on a mutable array, or set it as the object
// for the key 'letter' on a mutable dict
}
And of course you could further optimize this approach by implementing a method for filtering the array based on a letter. I hope that this makes sense.

How to filter array of NSDictionary for key separated by comma

I have an array of NSDictionary.NSDictionary has a key named as multiple_image key that contain string separated by ,.
I want set of array that contain 123.png for multiple_images key.
Can some one show me how to do this using NSPredicate or without predicate.
//Array
{
Image = "<UIImage: 0xf72df30>";
active = yes;
"admin_id" = 169;
"category_id" = 32;
"chef_id" = 175;
descr = "Cool tea to cool down the mind.";
id = 110;
"multiple_images" = "Jellyfish.jpg,345.png";
name = "Southern Sweet Ice Tea";
price = 160;
rating = 3;
selected = 0;
"subcat_id" = 23;
"tag_id" = 45;
"tax_id" = 10;
"tax_value" = "12.00";
},
{
Image = "<UIImage: 0xf72ebd0>";
active = yes;
"admin_id" = 169;
"category_id" = 31;
"chef_id" = 175;
descr = "Ingredients are almonds or cashews. No hydrogenated stuff, no extra weirdo ingredients";
id = 107;
"multiple_images" = "Jellyfish.jpg,123.png";
name = "Butter Chicken";
price = 300;
rating = 3;
selected = 0;
"subcat_id" = 24;
"tag_id" = 43;
"tax_id" = 9;
"tax_value" = "0.00";
},
{
Image = "<UIImage: 0xf72f870>";
active = yes;
"admin_id" = 169;
"category_id" = 31;
"chef_id" = 173;
descr = "Raw vegetables including carrots, cucumbers.";
id = 100;
"multiple_images" = "Jellyfish.jpg,shake.png,";
name = Salads;
price = 50;
rating = 3;
selected = 0;
"subcat_id" = 22;
"tag_id" = 44;
"tax_id" = 9;
"tax_value" = "0.00";
}
Using predicates,
[array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"multiple_images CONTAINS '123'"]];
Using predicates, but with blocks
NSArray *filtered = [test filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:
^BOOL(NSDictionary *evaluatedObject, NSDictionary * bindings) {
NSString *key = #"123";
return ([evaluatedObject[#"multiple_images"] rangeOfString:key].location != NSNotFound);
}]];
Try
NSDictionary *item = mainArray[0];
NSString *imagesString = item[#"multiple_images"];
NSArray *images = [imagesString componentsSeparatedByString:#","];
Now you can use the images
Try this code
for (int i=0; i<[mainArray count]; i++) {
NSDictionary *item = [mainArray objectAtIndex:i];
NSString *imagesString = item[#"multiple_images"];
NSArray *images = [imagesString componentsSeparatedByString:#","];
for (int j=0;j<[images count]; j++) {
if ([[images objectAtIndex:j] isEqualToString:#"123.png"]) {
///Your Required code;
}
}
}
So you want to save the dictionary that has 123.png.
maybe you can try something like this:
NSMutableArray *arr = [NSMutableArray new];// your array of objects(dictionaries)
__block NSMutableArray *images123 = [NSMutableArray new];
[arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSMutableDictionary *dictionary = (NSMutableDictionary *)obj;
if([[dictionary allKeys]containsObject:#"multiple_images"]){
NSString *imageList = (NSString *)[dictionary objectForKey:#"multiple_images"];
NSArray *arrayImages = [imageList componentsSeparatedByString:#","];
if([arrayImages containsObject:#"123.png"]){
[images123 addObject:dictionary];
}
}
}];

Filtering NSArray/NSDictionary using NSPredicate

I've been trying to filter this array (which is full of NSDictionaries) using NSPredicate...
I have a very small amount of code that just isn't working...
The following code should change label.text to AmyBurnett34, but it doesn't...
NSPredicate *pred = [NSPredicate predicateWithFormat:#"id = %#", [[mightyPlistDict objectForKey:#"pushesArr"] objectAtIndex:indexPath.row]];
NSLog(#"%#",pred);
label.text = [[[twitterInfo filteredArrayUsingPredicate:pred] lastObject] objectForKey:#"screen_name"];
NSLog(#"%#",twitterInfo);
And here is what gets NSLoged...
2012-08-05 11:39:45.929 VideoPush[1711:707] id == "101323790"
2012-08-05 11:39:45.931 VideoPush[1711:707] (
{
id = 101323790;
"screen_name" = AmyBurnett34;
},
{
id = 25073877;
"screen_name" = realDonaldTrump;
},
{
id = 159462573;
"screen_name" = ecomagination;
},
{
id = 285234969;
"screen_name" = "UCB_Properties";
},
{
id = 14315150;
"screen_name" = MichaelHyatt;
}
)
Just for the heads up if you also NSLog this... the array is empty...
NSLog(%#,[twitterInfo filteredArrayUsingPredicate:pred]);
The problem is that your predicate is using comparing with a string and your content is using a number. Try this:
NSNumber *idNumber = [NSNumber numberWithLongLong:[[[mightyPlistDict objectForKey:#"pushesArr"] objectAtIndex:indexPath.row] longLongValue]];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"id = %#", idNumber];
You don't know for sure that the value of "id" is a string - it might be a NSNumber. I suggest:
NSUInteger matchIdx = ...;
NSUInteger idx = [array indexOfObjectPassingTest:^BOOL(NSDictionary *dict, NSUInteger idx, BOOL *stop)
{
id obj = [dict objectForKey:#"id"];
// NSLog the class if curious using NSStringFromClass[obj class];
NSUInteger testIdx = [obj integerValue]; // works on strings and numbers
return testIdx == matchIdx;
}
if(idx == NSNotFound) // handle error
NSString *screenName = [[array objectAtIndex:idx] objectForKey:#"screen_name"];
NSPredicate is used for filtering arrays, not sorting them.
To sort an array, use the sortedArrayUsingDescriptors method of NSArray.
An an example:
// Define a sort descriptor based on last name.
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"lastName" ascending:YES];
// Sort our array with the descriptor.
NSArray *sortedArray = [originalArray sortedArrayUsingDescriptors:[NSArray arrayWithObjects:descriptor, nil]];

Objective-C -> Remove Last Element In NSDictionary

EDIT:
The Code:
//stores dictionary of questions
- (void)requestFinished:(ASIHTTPRequest *)request
{
NSData *responseData = [request responseData];
NSString *json = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSDictionary *qs = [json objectFromJSONString];
self.questions = qs;
NSLog(#"%#", questions);
[json release];
[self setQuestions];
[load fadeOut:load.view withDuration:0.7 andWait:0];
UIBarButtonItem *anotherButton = [[UIBarButtonItem alloc] initWithTitle:#"Start" style:UIBarButtonItemStylePlain target:self action:#selector(start:)];
self.navigationItem.rightBarButtonItem = anotherButton;
}
I have the following items in an NSDictionary:
(
{
max = 120;
min = 30;
question = "Morning Bodyweight (Kg)";
questionId = 1;
questionNumber = 1;
sectionId = 1;
type = TextInput;
},
{
question = "Morning Urine Colour";
questionId = 2;
questionNumber = 2;
sectionId = 1;
type = ImagePicker;
},
{
max = 120;
min = 30;
question = "Evening Bodyweight (Kg)";
questionId = 3;
questionNumber = 3;
sectionId = 1;
type = TextInput;
},
{
question = "Evening Urine Colour";
questionId = 4;
questionNumber = 4;
sectionId = 1;
type = ImagePicker;
},
{
max = 90;
min = 40;
question = "Morning Heart Rate (BPM)";
questionId = 5;
questionNumber = 5;
sectionId = 1;
type = TextInput;
},
{
question = "Time of Month (TOM)";
questionId = 6;
questionNumber = 6;
sectionId = 1;
type = Option;
}
)
I want to remove the last element:
{
question = "Time of Month (TOM)";
questionId = 6;
questionNumber = 6;
sectionId = 1;
type = Option;
}
Is there a pop() equivalent for the NSDictionary? If not how is it possible to remove the last element?
There is no order to dictionaries so there is no 'last object'
However, this might solve your problem, though it might not always remove what you are thinking the 'last object' is:
[dictionaryName removeObjectForKey:[[dictionaryName allKeys] lastObject]];
This looks to be (or could be made to be) an array of dictionaries. If you have these dictionaries as the objects of an NSMutableArray, then you can use – removeLastObject. Otherwise, you're SOL since even NSMutableDictionary has no such method.
There is no last element in a dictionary, as elements in a dictionary are not ordered.
Can you somehow get the element by using the key value? NSDictionaries don't have an ordering, so there's no such thing as removing the "last" element.
I think that's an array of NSDictionaries you got yourself there. In which case it's very easy to do:
NSMutableArray *mArray = [NSMutableArray arrayWithArray:array]; // if not mutable
[mArray removeLastObject];