Reputation: 351
NSMutableArray *array = [NSMutableArray arrayWithObjects:@{@"name":@"Jenny",@"age":@23},@{@"name":@"Daisy",@"age":@27},nil];
Is it possible to remove object by key in the array's dictionary object?
For example. remove object by age = 27
Upvotes: 4
Views: 3238
Reputation: 9835
I'm not sure if there's a more direct method or not, but one way to do it would be to simply iterate through the array and test the values. You can't mutate an array while enumerating, meaning you cant remove an object while iterating through it, so one method is to obtain the index of the object that matches your criteria, and if you find one, break, and remove the item at that index. Something like the following:
NSInteger indexToDelete = -1;
for (NSInteger i = 0; i < array.count; i++) {
NSDictionary *dict = array[i];
if ([dict[@"age"] integerValue] == 27) {
indexToDelete = i;
break;
}
}
if (indexToDelete > 0) {
[array removeObjectAtIndex:indexToDelete];
}
Intrigued by the other answers using filteredArrayUsingPredicate
, I was curious about performance and decided to do a side-by-side performance test using Xcode's measureBlock
feature. Iterating through an array of 1,000 dictionaries, removing one item that matches an integer value from each array, and comparing when the item is very close to the beginning of the array, the middle of the array, and the end of the array, both versions tended to complete within a few thousandths of a second of the other, with the predicate filter being very slightly faster in every case. (We're talking around .269 seconds vs .261 seconds)
With that in mind, I would think that neither is better than the other in any major sense, it just comes down to preference. I do think the filteredArrayUsingPredicate method is cleaner though. Just some additional food for thought for anyone curious, and gave me a reason to try out the measureBlock feature on my own. :)
Upvotes: 3
Reputation: 535129
To filter objects out of an NSArray, call filteredArrayUsingPredicate
:
NSArray *array = @[@{@"name":@"Jenny",@"age":@23},@{@"name":@"Daisy",@"age":@27}];
NSArray *array2 =
[array filteredArrayUsingPredicate:
[NSPredicate predicateWithBlock:^BOOL(id obj, NSDictionary *d) {
return ![[obj valueForKey:@"age"] isEqual:@27];
}]];
Now array2
is the desired array - it is the first array without the one whose age is 27.
By the way, I know this is not what you asked, but that sort of thing is a great reason to switch to Swift. It is soooooo much simpler; this sort of problem is like a living neon technicolor advertisement for Swift:
let array = [["name":"Jenny", "age":23],["name":"Daisy", "age":27]]
let array2 = array.filter {$0["age"] != 27}
Upvotes: 8
Reputation: 34829
You can use NSPredicate
to create a new array that's missing the unwanted entry. NSPredicate
is similar to a database query where the input NSArray represents the database, and the output array is the response to the query.
NSArray *array = @[ @{@"name":@"Jenny",@"age":@23},
@{@"name":@"Daisy",@"age":@27} ];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age != 27"];
NSArray *filtered = [array filteredArrayUsingPredicate:predicate];
NSLog( @"%@", array );
NSLog( @"%@", filtered );
Upvotes: 4
Reputation: 7549
In this case, you'll have to loop through each item and do a manual test against each object, which may be fine depending on the size of data you're dealing with and the complexity of your use cases.
Alternatively, consider storing the data in a sqlite database and querying against it if it's practical for you.
Upvotes: 1