Matoe
Matoe

Reputation: 2758

Split NSString with multiple delimiters?

For text bozo__foo!!bar.baz, how to split an NSString containing this into (bozo, foo, bar, baz)?

That is, separe it in components with strings (delimiters) __, !! and ..

Upvotes: 7

Views: 6286

Answers (5)

Bart Herrijgers
Bart Herrijgers

Reputation: 1

I solved it for my project by looking for the longest separator, replacing the others with this one, then do the separation on the only one left. Try this:

  NSString *test = @"bozo__foo!!bar.baz";
  test = [test stringByReplacingOccurrencesOfString:@"!!" withString:@"__"];
  test = [test stringByReplacingOccurrencesOfString:@"." withString:@"__"];
  NSArray<NSString *> *parts = [test componentsSeparatedByString:@"__"];

Upvotes: 0

Ievgen
Ievgen

Reputation: 2079

More functional solution is to apply -componentsSeparatedByString: recursively, for each component, which was derived during previous separator application:

NSString Category

- (NSMutableArray<NSString *> *)gvr_componentsSeparatedByStrings:(NSArray<NSString *> *)separators {
    if (separators.count == 0) {
        return [NSMutableArray arrayWithObject:self];
    }

    NSString *separator = [separators firstObject];

    NSArray *reducedSeparators = [separators gvr_arrayByRemovingFirstObject];

    NSArray *components = [self componentsSeparatedByString:separator];

    NSMutableArray *result = [NSMutableArray new];

    for (NSString *component in components) {
        NSMutableArray *subResult = [component gvr_componentsSeparatedByStrings:reducedSeparators];

        [result addObjectsFromArray:subResult];
    }

    return result;
}

NSArray Category

- (NSArray *)gvr_arrayByRemovingFirstObject {
    NSMutableArray *result = [NSMutableArray new];
    for (NSInteger i = 1; i < self.count; i++) {
        [result addObject:self[i]];
    }

    return [result copy];
}

Upvotes: 0

user2503304
user2503304

Reputation:

I'm aware that this question has already been answered but this is a way to separate strings using multiple strings. This is a category to NSString.

- (NSArray<NSString *> *)componentsSeparatedByStrings:(NSArray<NSString *> *)separators
{
    NSMutableArray<NSString *> *components = [[NSMutableArray alloc] init];
    unichar buffer[self.length + 1];
    NSInteger currentOrigin = 0;
    NSInteger currentLength = 0;

    [self getCharacters:buffer];

    for(NSInteger i = 0; i < self.length; i++)
    {
        unichar currentChar = buffer[i];

        currentLength++;

        for(NSInteger n = 0; n < separators.count; n++)
        {
            NSString *currentDivider = [separators objectAtIndex:n];

            if(currentDivider.length == 0)
            {
                return @[self];
            }
            else if(currentDivider.length > 1)
            {
                BOOL goodMatch = NO;

                for(NSInteger x = 0; x < currentDivider.length; x++)
                {
                    unichar charInDivider = [currentDivider characterAtIndex:x];

                    if(charInDivider == currentChar)
                    {
                        goodMatch = YES;
                    }
                    else
                    {
                        goodMatch = NO;
                        break;
                    }

                    if(goodMatch == YES && ((x + 1) != currentDivider.length))
                    {
                        i++;
                        currentLength++;

                        currentChar = buffer[i];
                    }
                }

                if(goodMatch == YES)
                {
                    NSRange newComponentRange = NSMakeRange(currentOrigin, (currentLength - currentDivider.length));
                    NSString *newComponent = [self substringWithRange:newComponentRange];
                    currentOrigin = (i + 1);
                    currentLength = 0;

                    [components addObject:newComponent];
                    NSLog(@"%@", components);
                }
            }
            else // If current divider is only one character long.
            {
                if([currentDivider characterAtIndex:0] == currentChar)
                {
                    NSRange newComponentRange = NSMakeRange(currentOrigin, (currentLength - 1));
                    NSString *newComponent = [self substringWithRange:newComponentRange];
                    currentOrigin = (i + 1);
                    currentLength = 0;

                    [components addObject:newComponent];
                    break;
                }
            }
        }

        // Handle the end of the string.
        if((i + 1) == self.length)
        {
            NSRange newComponentRange = NSMakeRange(currentOrigin, currentLength);
            NSString *newComponent = [self substringWithRange:newComponentRange];
            currentOrigin = 0;
            currentLength = 0;

            [components addObject:newComponent];
        }
    }

    return components;
}

Example: "ABCD__EFGHI__JKLMNOP-QRST.UV_WXYZ"

NSLog(@"%@", [test componentsSeparatedByStrings:@[@"__", @"-", @"."]]);

Log Result: "(ABCD, EFGHI, JKLMNOP, QRST, "UV_WXYZ")"

Upvotes: 1

prakhar
prakhar

Reputation: 828

You can split the strings using NSCharacterSet. Try this

NSString *test=@"bozo__foo!!bar.baz";
NSString *sep = @"_!.";
NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:sep];
NSArray *temp=[test componentsSeparatedByCharactersInSet:set];
NSLog(@"temp=%@",temp);

Upvotes: 22

Tonnie
Tonnie

Reputation: 169

NSString *text = @"bozo__foo!!bar.baz";

NSArray *split1 = [text componentsSeparatedByString:@"__"];
NSArray *split2 = [[split1 lastObject] componentsSeparatedByString:@"!!"];
NSArray *split3 = [[split2 lastObject] componentsSeparatedByString:@"."];

NSLog(@"%@, %@, %@, %@", split1[0], split2[0], split3[0], split3[1]);

Upvotes: 0

Related Questions