Delete Specific Items from NSMutableArray - ios

I'm trying to perform the relatively simple task of deleting the items in an NSMutableArray that fit a certain criteria.
In this particular case, I'd like to delete the items where all of the following are true:
city: Seattle
state: WA
timestamp: more than 60 seconds old
An NSLog of my array looks like this:
array = (
{
city = "Seattle";
state = "WA";
timestamp = 1432844384;
},
{
city = "Dallas";
state ="TX";
timestamp = 1432844415;
},
{
city = "Seattle";
state = "WA";
timestamp = 1432845329;
}
)
I've tried using NSPredicate to filter the array, but I think that may be overcomplicating things. Any recommendations would be great! Thank you!

You could get the indexes of such elements by using indexesOfObjectsPassingTest: (see docs)
NSIndexSet *indexes = [array indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
// check if obj is matching all your criteria
}
Then remove the items using removeObjectsAtIndexes: (see docs)
[array removeObjectsAtIndexes:indexes];

No, filtering out the items to delete and then deleting them is the right way. It iw not complicated, because obviously getting the specified items is filtering with a predicate + deleting them is deleting them. How could a solution be less complicated?
Maybe it is easier to you, to filter out the items not to delete. Simply add a NOT to your predicate.

Here your timestamp is unique every time. So you have delete data base on timestamp.
First you have to get index of that timestamp from that array.
NSInteger index = [[array valueForKey:#"timestamp"] indexOfObject:timestamp];
After getting this index of array you have to delete data from that index.
[array removeObjectAtIndex:index];

Related

How to access index of NSMutable Array in Objective-C?

for(int i=0;i<[serviceNamesFilterArray count];i++){
NSLog(#"state : %#", [serviceNamesFilterArray objectAtIndex:i]);
NSString *str = [serviceNamesFilterArray objectAtIndex:i];
if (tag_id == [serviceNamesFilterArray indexOfObject:str] ) {
// filterButtonArray = serviceNamesFilterArray;
[filterButtonArray addObject:str];
NSLog(#"%#",filterButtonArray);
}
}
I want to access index of serviceNamesFilterArray. How can i access index's of my array so that i can compare it with integer tag_id?
Even Objective-C provides smarter filter APIs than a loop.
index will contain the index of the object in the array matching tag_id
NSInteger index = [self.serviceNamesFilterArray indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
return (NSString *)obj.integerValue == tag_id;
}];
you can compare i value with your tag_id as follows:
for(int i=0;i<[serviceNamesFilterArray count];i++) {
NSLog(#"state : %#", [serviceNamesFilterArray objectAtIndex:i]);
NSString *str = [serviceNamesFilterArray objectAtIndex:i];
if (tag_id == i) {
//perform your logic here
}
}
you can use the enumerateObjectsUsingBlock method, like
[serviceNamesFilterArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
// ...
}];
Preamble: you are using [array objectAtIndex:index] in your code, while this was the way to index historically in modern Objective-C you simply write array[index]. If you are learning Obj-C from a book/website you might want to look for a newer text.
It is unclear what you are asking let’s see what we can figure out.
You start with a loop:
for(int i=0;i<[serviceNamesFilterArray count];i++)
Here i is going to be used as an index into the array serviceNamesFilterArray. Inside the loop you then access the object at index i (updating your code as above):
NSString *str = serviceNamesFilterArray[i];
and having obtained the object at index i you ask what is the index of that object:
[serviceNamesFilterArray indexOfObject:str]
There are two possible answer here:
i – this is the most obvious answer and will be the result if there are no duplicates in serviceNamesFilterArray. It will be the answer as you just obtained str from index i of the array.
j where j < i – this will be the answer if the array contains duplicates and the same string is found at indices j and i. This result happens because indexOfObject: returns the first index at which the object occurs with the array.
The most likely result seems to be (1) in your case (guessing you do not have duplicate “service names”). In this case your conditional is equivalent to:
if (tag_id == i) {
[filterButtonArray addObject:str];
}
However if this is your intention then the loop is completely unnecessary as your code is equivalent to:
NSString *str = serviceNamesFilterArray[tag_id];
[filterButtonArray addObject:str];
If the serviceNamesFilterArray does contain duplicates then your code as written may add the string at index tag_id multiple times to filterButtonArray or it may add it no times – we'll leave figuring out why as an exercise, and we doubt this is your intention anyway.
At the time of writing #vadian has made a different guess as to your aim. Their solution finds the index, if any, where the string value if interpreted as an integer is equal to the value of tag_id (an integer). If that is your aim then #vadian’s solution provides it.
Of course both our and #vadian’s guesses might be wrong at to what your aim is. If so you can edit the question to explain, or delete it and ask a new one instead – given this question has at the time of writing 3 answers already deletion in this case might be better to reduce future confusion when people read the (revised) question and (outdated) answers.
HTH
Maybe you just need to judge whether the tag_id is less than count of serviceNamesFilterArray, then you can get the value by tag_id directlly.
if (tag_id < [serviceNamesFilterArray count]){
NSString *str = [serviceNamesFilterArray objectAtIndex:tag_id];
// other logic here
}

IOS/Objective-C: Search string element with array of objects

As part of an autocomplete box, I am searching names within an array of contacts. However, after the user picks a name from the suggested List, I need to grab the id of the contact which is in the array of contact objects but not the array of names that appear in the suggest box. I've been working with just the names as that's what I want to display in the suggestion box but have an array of contacts as well.
How would I convert code below (probably using key values) to search the name dimensions of an array of objects instead of an array of names so as to keep track of the ids of the objects. I am kind of fuzzy on arrays and key values.
//the array being searched looks something like #[#"John", #"Dave", #"Sam", #"Xian", #"Ahmed", #"Johann"];
//I want to search the names in an array that looks something like:
(
{
first = "John";cid = 2;},
{
first = "Dave";cid = 44;},
{
first = "Xian";cid=99})
//this code works great to search names but I lose track ids. Thank you for any suggestions.
-(void)searchArray: (NSMutableArray*) array forString: (NSString *) term {
[_contactsSuggested removeAllObjects];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#",term];
NSArray *tempArray = [array filteredArrayUsingPredicate:predicate];
_contactsSuggested = [NSMutableArray arrayWithArray:tempArray];
[_autocompleteTableView reloadData];
}
Create a Contact object. Give it a name property, an id property, and any other properties you need. Then write code that searches an array of Contact objects rather than just an array of names. You could then create a predicate using predicateWithBlock to filter the items that match your name property.

Getting distinct rows from Realm table in iOS

I am using Realm database for iOS application where i have a use case in which i want to filter result set by distinct values for a particular field. This field is not a primary key of the realm table.
I was not able to construct query for that.
Sample query :
RLMResults *allFiles = [FileRLMObject objectsInRealm:realmObject where:#"colA == %#", #"test1"];
FileRLMObject is a subclass of RLMObject from realm library
here table contains one column with name colB. While getting allFiles results, i want to get rows which are having distinct colB values.
Any suggestions how i can achieve this?
Realm doesn't support distinct queries yet. You can subscribe issue #1103 to track progress on that.
As a workaround, you could query for all values for colB first and then select objects for each value of it, as seen below:
NSArray *values = [FileRLMObject.allObjects valueForKey:"type"];
NSSet *distinctValues = [NSSet setWithArray:values];
NSMutableArray *allFiles = [NSMutableArray new];
for (NSString *colB in distinctValues) {
// This takes the firstObject.
// You might want to modify the sort order to make sure
// you get a certain object in case that there may exist
// multiple objects per distinct value.
FileRLMObject *object = [FileRLMObject objectsWhere:#"colB == ?", colB].firstObject;
[allFiles appendObject:object];
}

How can I implement my logic properly to populate my UITableView

Sorry guys, this problem I am running into is pretty trivial. I just can't wrap my head around it so hope someone can help me. Your help is really appreciated. I am getting JSON data through NSURLConnectDelegate with a web API. I get something like this back:
(
{
id = 340
name = Vicent },
{
id = 339
name = Johny },
{
id = 338
name = Eric }
)
and I save it in a NSMutableArray as a global variable. Now, I have a NSSet of "ids". For example:
{
340, 339
}
In the numberOfRowsInSection, I return the set's count. I am trying to load only the ids in the NSSet from the array with the data saved from the webAPI, so I do something like this in cellForRowIndexPath:
for (NSNumber *num in [set allObjects]) {
NSString *newString = [[savedArray objectAtIndex:indexPath.row]
NSString *new = [num stringValue];
if ([new isEqual:newString]) {
}}
How can I just populate the ids I want?
The JSON makes it look like you have an array of dictionaries, which is a reasonable data structure to use as the data source for a table view.
It sounds like you're trying to filter your array to only include the items that are in your set. Is that right?
If so, you could write code that would create a new array containing the subset of your array elements who's ID is also in your set. There are at least a half-dozen ways to do that. One fairly simple approach would be to use the NSArray method indexesOfObjectsPassingTest. You'd pass that method a block of code that would check each array element to see if it's id object was in your set.
That would give you an NSIndexSet with the indexes of the items in your array who's ID are in your set. Then you could use the NSArray method objectsAtIndexes to get an array of only the objects that are also in the set. Something like this (Assuming that your array of dictionaries is called savedArray and your set is called allObjects:
//get the indexes of items in the array savedArray who's id appears in the set allObjects
NSIndexSet *indexes = [savedArray indexesOfObjectsPassingTest:
^(NSDictionary *obj,
NSUInteger idx,
BOOL *stop)
{
return [allObjects member: obj[#"id"]] != nil;
}
];
//Now build an (immutable) array of just the objects who's ID are in the set
NSArray *subArray = [savedArray objectsAtIndexes: indexes];
The array subArray created above is immutable. If you need a mutable array you would need to make a mutable copy, which is a one-line change.
Disclaimer: I still struggle a little with block syntax, so the above might not be exactly correct, but it gives you the general idea.

How do I store a maximum amount of 5 objects in a NSMutableArray?

I am creating an array of NSdictionarys and putting that array in NSUserDefaults. I then put the array data in a recently added tableview. I am trying to get it so it would store the 5 most recent objects added to that array. How can I go about this? Below is my code:
- (IBAction)searchButton:(UIButton *)sender {
[_jobDic setObject:_jobField.text forKey:#"jobRecent"];
[_jobDic setObject:_locationField.text forKey:#"locationRecent"];
[_recentJobArray addObject:_jobDic];
[_recentDefaults setObject:_recentJobArray forKey:#"recentJobs"]
[_recentDefaults synchronize];
}
Assuming you are referring to the _recentJobArray, you could do this:
if (_recentJobArray.count == 5) {
[_recentJonArray removeObjectAtIndex:0]; // remove oldest
}
[_recentJobArray addObject:_jobDic];
If you keep your array sorted in newest-to-oldest order then maddy's solution will work well. Otherwise you'll need to save a date key/value pair in each dictionary, and then loop through the array looking for the oldest item. The code might look something like this
NSDictionary *oldest;
for (NSDictionary *aJobDict in _recentJobArray)
{
NSDate *dateOfThisDict = aJobDict[#"date"]; //Assumes each dict has a key #"date"
if (!oldest || [oldest[#"date"] compare: dateOfThisDict] == NSOrderedDesending)
oldest = aJobDict;
}
[_recentJobArray removeObject: oldest];
[_recentJobArray addObject: newDict];

Resources