I have:
self.path = [self pathByCopyingFile:#"Notes List.plist"];
self.data = [[NSMutableDictionary alloc] initWithContentsOfFile:self.path];
self.notes = [self.data objectForKey:#"Notes"];
Then in a button (Button method definitely gets called):
NSString *title = self.navigationItem.title;
//Filter notes array by title
NSPredicate *pred = [NSPredicate predicateWithFormat:#"Title =[cd] %#", title];
NSArray * titleArray = [self.notes filteredArrayUsingPredicate:pred];
//delete all the notes with the old title name
[self.notes removeObject:titleArray];
NSLog(#"%#", self.notes);
At this point, self.notes still contains the items and i dont know why they arnt being removed
You are trying to remove an array from the array. That's not what you want. I believe your goal is to remove all of the objects in the titleArray from your notes array.
And this doesn't even consider that self.notes is probably an NSArray and not an NSMutableArray.
If self.notes is mutable you can use the removeObjectsInArray:.
[self.notes removeObjectsInArray:titleArray];
Related
Hello I have a NSMutableDictionary like this
<__NSArrayM 0x14e226ff0>(
{
DocumentName = "IMG_2597.JPG";
DocumentType = JPG;
Image = "<UIImage: 0x14e52c370> size {1239, 1242} orientation 0 scale 1.000000";
}
I am adding several objects into my NSMutablearray. But I want to check whether this image already available in the NSMutablearray. Actually I am planing to search it by the DocumentName. How can I check whether that same value is already exists for the DocumentName key in the array. I want to add the NSMutableDictionary if only its not already exists. This is how I create my NSMutabledictionaryobject.
NSMutableDictionary *imageDictionary=[[NSMutableDictionary alloc] init];
[imageDictionary setObject:chosenImage forKey:#"Image"];
[imageDictionary setValue:strDocNAme forKey:#"DocumentName"];
[imageDictionary setValue:strExtension forKey:#"DocumentType"];
[mutarrayImages addObject:imageDictionary];
Please help me.
Thanks
You can try one of these to check image is already exist or not.
1) Using predicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"DocumentName = 'IMG_2597.JPG'"];
NSArray *arr = [yourArray filteredArrayUsingPredicate:predicate];
if (arr.count > 0) {
NSLog(#"Object is contain");
}
2) Using valueForKey
NSArray *documentName = [yourArray valueForKey:#"DocumentName"];
if ([documentName containsObject:#"IMG_2597.JPG"]) {
NSLog(#"Object is contain");
}
NSSet* myValuesSet = [NSSet setWithArray: [mutarrayImages valueForKey:#"DocumentName"]];
if ([[myValuesSet allObjects] containsObject:< DocumentName to compare >]) {
NSLog(#"Exist");
}
else{
NSLog(#"Does not exist");
}
NSArray *allObjectsArray; // your array
NSMutableArray *resultObjectsArray = [NSMutableArray array];
for(NSDictionary *dict in allObjectsArray)
{
NSString *docName = [dict objectForKey:#"DocumentName"];
NSRange range = [docName rangeOfString:#"your string which you want to match" options:NSCaseInsensitiveSearch];
if(range.location != NSNotFound)
[resultObjectsArray addObject:dict];
}
I have an array having objects with different properties. I want to create an array of sets which contain objects with same value of a single property of the object.
Suppose this is an array of object which has property a and b
1: {a:10, b:5}, 2: {a:2,b:5}, 3: {a:20,b:5}, 4: {a:5,b:5}, 5: {a:4,b:20}, 6: {a:51,b:20}
I want to create another array of NSSet of objects with distinct values of property b
so the result would be the following Array of 2 NSSet
1: {a:10, b:5}, {a:2,b:5}, {a:20,b:5}, {a:5,b:5}
2: {a:4,b:20}, {a:51,b:20}
How can this be done?
I'd do this by first creating a dictionary of sets where the keys of the dictionary are the unique values of "b".
Note: This is untested code. There could be typos here.
NSArray *objectArray = ... // The array of "SomeObject" with the "a" and "b" values;
NSMutableDictionary *data = [NSMutableDictionary dictionary];
for (SomeObject *object in objectArray) {
id b = object.b;
NSMutableSet *bSet = data[b];
if (!bSet) {
bSet = [NSMutableSet set];
data[b] = bSet;
}
[bSet addObject:object];
}
NSArray *setArray = [data allValues];
setArray will contain your array of sets.
This codes also assumes you have a sane isEqual: and hash implementation on your SomeObject class.
This is how you can do this:
NSArray *data = #[#{#"a":#10, #"b":#5}, #{#"a":#2,#"b":#5}, #{#"a":#4,#"b":#20}, #{#"a":#51,#"b":#20}];
NSSet *bSet = [NSSet setWithArray: [data valueForKey: #"b"]];
NSMutableArray *filteredArray = [[NSMutableArray alloc] initWithCapacity: bSet.count];
for (NSNumber *bValue in bSet) {
NSPredicate *anArrayFilterPredicate = [NSPredicate predicateWithBlock:^BOOL(NSDictionary *aDictionaryData, NSDictionary *bindings) {
if ([aDictionaryData[#"b"] isEqual:bValue]) {
return YES;
}
return NO;
}];
NSArray *uniqueBValueArray = [data filteredArrayUsingPredicate:anArrayFilterPredicate];
[filteredArray addObject:uniqueBValueArray];
}
NSLog(#"filteredArray = %#", filteredArray);
Using Key-Value coding collection operators, we can get the array of distinct values for an object. Then you could easily compute the results you want.
In your case this could be done like this.
NSArray *arrayOfDistinctObjects = [array valueForKeyPath:#"#distinctUnionOfObjects.b"];
NSMutableArray *newSetArray = [NSMutableArray new];
for (id value in arrayOfDistinctObjects) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.b == %#", value];
NSArray *filterArray = [array filteredArrayUsingPredicate:predicate];
NSSet *newSet = [NSSet setWithArray:filterArray];
[newSetArray addObject:newSet];
}
where array is the array of objects on which you wanna operate.
arrayOfDistinctObjects gives you the array of distinct values for b.
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. :)
I have an NSMutableArray of friends that contains Parse.com PFUser objects. Each PFUser has a NSString field. I want to search this array for an object containing a specific string. So far I am using this :
NSString username = "bob";
PFUser *user = [[PFUser alloc] init];
for(PFUser *userItem in self.currentUser.friends) {
if([user.username isEqualToString:username]) {
user=userItem;
}
}
Is there a better way to do this? Is this much slower than using an NSMutable dictionary and then just pulling out the object that way? My array size is around 100. Thanks
Modify ur code as below..using NSMutableArray..only
NSString username = "bob";
PFUser *user = [[PFUser alloc] init];
for(PFUser *userItem in self.currentUser.friends) {
//In your code it is written as user.username instead of userItem.username..check it..
if([userItem.username isEqualToString:username]) {
user=userItem;
break;//exit from loop..Results in optimisation
}
}
Using Predicate..of array of objects
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", username];
NSArray *results = [self.currentUser.friends filteredArrayUsingPredicate:predicate];
PFUser *user=[[PFUser alloc]init];
user=[results objectAtIndex:0];//here is the object u need
Hope it helps you..!
Use NSPredicate, it should look something like this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.object.stringInsideObject LIKE %#", stringToCompare];
NSArray *filteredArray = [[NSArray alloc] initWithArray:[yourArray filteredArrayUsingPredicate:predicate]];
Try This,
- (PFUser *)filterUserObjectWithName:(NSString *)userName
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.username == %#",userName];
NSArray *results = [self.currentUser.friends filteredArrayUsingPredicate:predicate];
return results.count ? [results firstObject]: nil;
}
Hope this helps
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF. username contains[c] %#", stringToCompare];
NSArray *filteredArray = [[NSArray alloc] initWithArray:[yourArray filteredArrayUsingPredicate:predicate]];
Hope this will help you.
I have an array which contains multiple Dictionaries each one with 3 keys (#"date", #"username", #"text").
What I want to check for, is whether the same user (#"username") exists in more than one dictionary in that Array. And, if she does, combine the text for those "duplicates" into one dictionary.
I have considered this answer to check for duplicates and this one
but I cannot figure out how to combine these two.
Jumping in here because although I think you should work on the code yourself first, I think Miro's answer is more complicated than the issue requires and though I like the idea of using predicates in Greg's answer, here's a 3rd solution that (1) wouldn't require you to change your data structure and (2) references the necessary loops...
The way I'd do it: Create an NSMutableArray then start adding the usernames in order. If the NSMutableArray already contains the username though, don't add another instance of the username, but instead merge the dictionary info.
ex.
// Note: I'm calling your array of user dictionaries userArray.
// Create a username array to store the usernames and check for duplicates
NSMutableArray *usernames = [[NSMutableArray alloc] init];
// Create a new userArray to store the updated dictionary info, merged
// entries et. al.
NSMutableArray *newUserArray = [[NSMutableArray alloc] init];
// Go through the array of user dictionaries
for (NSDictionary *userDict in userArray) {
// If the usernames array doesn't already contain the username,
// add it to both the usernames array and the newUserArray as is
if (![usernames containsObject:[userDict objectForKey:#"username"]]) {
[usernames addObject:[userDict objectForKey:#"username"]];
[newUserArray addObject:userDict];
}
// Otherwise, merge the userArray entries
else {
// Get a mutable copy of the dictionary entry at the first instance
// with this username
int indexOfFirstInstance = [usernames indexOfObject:[userDict objectForKey:#"username"]];
NSMutableDictionary *entry = [[newUserArray objectAtIndex:indexOfFirstInstance] mutableCopy];
// Then combine the "text" or whatever other values you wanted to combine
// by replacing the "text" value with the combined text.
// (I've done so with a comma, but you could also store the value in an array)
[entry setValue:[[entry objectForKey:#"text"] stringByAppendingString:[NSString stringWithFormat:#", %#", [userDict objectForKey:#"text"]]] forKey:#"text"];
// Then replace this newly merged dictionary with the one at the
// first instance
[newUserArray replaceObjectAtIndex:indexOfFirstInstance withObject:entry];
}
}
Maybe something like this [untested] example? Loop through, maintain a hash of existing items, and if a duplicate is found then combine with existing and remove.
NSMutableArray main; // this should exist, with content
NSMutableDictionary *hash = [[NSMutableDictionary alloc] init];
// loop through, backwards, as we're attempting to modify array in place (risky)
for(int i = [main count] - 1; i >= 0; i--){
// check for existing
if(hash[main[i][#"username"]] != nil){
int existingIdx = [hash[main[i][#"username"]] integerValue]; // get existing location
main[existingIdx][#"text"] = [main[existingIdx][#"text"] stringByAppendingString:main[i][#"text"]]; // "combine text" .. or however you'd like to
[main removeObjectAtIndex:i]; // remove duplicate
} else {
[hash setValue:[[NSNumber alloc] initWithInt:i] forKey:main[i][#"username"]]; // mark existance, with location
}
}
If you use NSMutableDictionary, NSMutableArray and NSMutableString you can do it with predicate like that:
NSMutableDictionary *d1 = [#{#"username": #"Greg", #"text" : [#"text 1" mutableCopy]} mutableCopy];
NSMutableDictionary *d2 = [#{#"username": #"Greg", #"text" : [#"text 2" mutableCopy]} mutableCopy];
NSMutableDictionary *d3 = [#{#"username": #"John", #"text" : [#"text 3" mutableCopy]} mutableCopy];
NSMutableArray *array = [#[d1, d2, d3] mutableCopy];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"username = %#", #"Greg"];
NSArray *filterArray = [array filteredArrayUsingPredicate:predicate];
NSMutableDictionary * firstDict = filterArray[0];
for (NSDictionary *d in filterArray)
{
if (firstDict != d)
{
[firstDict[#"text"] appendString:d[#"text"]];
[array removeObject:d];
}
}