Edi
Edi

Reputation: 1768

Filter strings that start as numbers or symbols to an NSArray with NSPredicate

How to filter strings that start as numbers or symbols to an NSArray with NSPredicate.

example:

array = {"John", "Mary", "Aroldo", "1John", "+Mary"}

to newArray = {"1John," "+Mary"}

Upvotes: 0

Views: 830

Answers (3)

Damian Carrillo
Damian Carrillo

Reputation: 1218

Here are 4 ways to do it. All of the examples make use of negated character classes. Your request was to filter out numbers and symbols, but you can also say that you want to filter out words that start with a nonalphabetic character.

- (void)testFilterArray0
{
    predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", @"[^a-zA-Z].*"];
    filtered = [unfiltered filteredArrayUsingPredicate:predicate];
    STAssertTrue([filtered isEqualToArray:expected], nil);
}

- (void)testFilteredArray1
{
    predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", @"[^\\p{L}].*"];
    filtered = [unfiltered filteredArrayUsingPredicate:predicate];
    STAssertTrue([filtered isEqualToArray:expected], nil);
}

- (void)testFilteredArray2
{
    predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", @"[^\\p{Letter}].*"];
    filtered = [unfiltered filteredArrayUsingPredicate:predicate];
    STAssertTrue([filtered isEqualToArray:expected], nil);
}

- (void)testFilteredArray3
{
    predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", @"[^\\p{General_Category=Letter}].*"];
    filtered = [unfiltered filteredArrayUsingPredicate:predicate];
    STAssertTrue([filtered isEqualToArray:expected], nil);
}

Upvotes: 6

Monolo
Monolo

Reputation: 18253

You can use a predicate with a regular expression to accomplish what you are after.

In general, the regex pattern you are looking for is "[chars].*" which will match any string that begins with c, h, a, r or s - in the example. You would substitute the actual chars you want to match.

To make the construct clearer, you can make a string of the actual chars you want to match, a string with the regular expression pattern and finally, the predicate.

If you are very comfortable with regular expressions and predicates, you can of course tighten it all up to a single line of code.

NSString *matchChars  = @"0123456789+-,."; // Add other characters you want to match

NSString *regexString  = [NSString stringWithFormat:@"[%@].*", matchChars];

NSPredicate *pred = [NSPredicate predicateWithFormat:@"self matches[cd] %@", regexString];

Upvotes: 0

Jean-Francois Gagnon
Jean-Francois Gagnon

Reputation: 3290

It doesn't use a NSPredicate, but it does the job

NSIndexSet *indexSet = [array indexesOfObjectsPassingTest:^BOOL(NSString *name, NSUInteger idx, BOOL *stop) {
    unichar ch = [name characterAtIndex:0];
    BOOL isLetter = (ch >= 65 && ch <= 90) || (ch >= 97 && ch <= 122);
    return !isLetter;
}];

NSArray *newArray = [array objectsAtIndexes:indexSet];

You might want to double check the return condition in the block, as I didn't test it.

Upvotes: 0

Related Questions