Reputation: 59
I am trying to filter out an array of strings based on their length. I'm completely new to Objective C and OOP in general.
wordList=[[stringFile componentsSeparatedByCharactersInSet:[NSCharacterSetnewlineCharacterSet]] mutableCopy];
for (int x=0; x<[wordList count]; x++) {
if ([[wordList objectAtIndex:x] length] != 6) {
[wordList removeObjectAtIndex:x];
}else {
NSLog([wordList objectAtIndex:x]);
}
}
for (int x=0; x<[wordList count]; x++) {
NSLog([wordList objectAtIndex:x]);
}
The NSLog in the else statement will only output 6 letter words, but the second NSLog outputs the entire array. What am I missing here? Also any general pointers to clean up/improve the code are appreciated.
Upvotes: 2
Views: 423
Reputation: 56625
Depending on what you feel is the easiest to understand you could either filter the array with a predicate or iterate over the array and remove objects. You should chose the approach that you have easiest to understand and maintain.
Predicates are a very concise way of filtering array or sets but depending on your background they may feel strange to use. You could filter your array like this:
NSMutableArray * wordList = // ...
[wordList filterUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
NSString *word = evaluatedObject;
return ([word length] == 6);
}]];
You cannot modify the array while enumerating it but you can make a note of all the items what you want to remove and remove them all in a batch after having enumerated the entire array, like this:
NSMutableArray * wordList = // ...
NSMutableIndexSet *indicesForObjectsToRemove = [[NSMutableIndexSet alloc] init];
[wordList enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSString *word = obj;
if ([word length] != 6) [indicesForObjectsToRemove addIndex:idx];
}];
[wordList removeObjectsAtIndexes:indicesForObjectsToRemove];
Upvotes: 3
Reputation: 726479
The problem with your code is that when you remove an item at index x
and move to the next index x++
, the item that was at x+1
is never examined.
The best way of filtering a mutable array is using the filterUsingPredicate:
method. Here is how you use it:
wordList=[[stringFile
componentsSeparatedByCharactersInSet:[NSCharacterSetnewlineCharacterSet]]
mutableCopy];
[wordList filterUsingPredicate:
[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary * bindings) {
return [evaluatedObject length] == 6; // YES means "keep"
}]];
Upvotes: 2