如何在找到两个或多个空白字符的位置拆分NSString?

时间:2018-06-15 18:23:15

标签: objective-c nsstring

给出字符串输入:

@"bonus pay savings            2.69 F";
@"brick and mortar             0.15-B";

所需的输出字符串:

[@"bonus pay savings", @"2.69 F"];
[@"brick and mortar", @"0.15-B"];

我试过这种方法:

NSString * str = @"bonus pay savings            2.69 F";
NSArray * arr = [str componentsSeparatedByString:@"   "];
NSLog(@"Array values are : %@",arr);

但我的方法的缺点是我使用3个空格作为分隔符,而空格的数量可以变化。如何实现这一目标?谢谢。

5 个答案:

答案 0 :(得分:0)

使用正则表达式的简单解决方案。

它用随机UUID字符串替换所有出现的2个或更多({2,})个空白字符(\\s)。然后它按该UUID字符串拆分字符串。

NSString *separator = [NSUUID UUID].UUIDString; 
NSString *string = @"bonus pay savings            2.69 F";
NSString *collapsedString =  [string stringByReplacingOccurrencesOfString:@"\\s{2,}"
                                                      withString:separator
                                                         options:NSRegularExpressionSearch
                                                           range:NSMakeRange(0, [string length])];
NSArray *output = [collapsedString componentsSeparatedByString:separator];
NSLog(@"%@", output);

答案 1 :(得分:0)

您可以使用NSRegularExpression拆分字符串。我们在NSString上创建一个类别:

NSString+asdiu.h

@interface NSString (asdiu)

- (NSArray<NSString *> *)componentsSeparatedByRegularExpressionPattern:(NSString *)pattern error:(NSError **)errorOut;

@end

NSString+asdiu.m

@implementation NSString (asdiu)

- (NSArray<NSString *> *)componentsSeparatedByRegularExpressionPattern:(NSString *)pattern error:(NSError **)errorOut {
    NSRegularExpression *rex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:errorOut];
    if (rex == nil) { return nil; }

    NSMutableArray<NSString *> *components = [NSMutableArray new];
    __block NSUInteger start = 0;
    [rex enumerateMatchesInString:self options:0 range:NSMakeRange(0, self.length) usingBlock:^(NSTextCheckingResult * _Nullable result, NSMatchingFlags flags, BOOL * _Nonnull stop) {
        NSRange separatorRange = result.range;
        NSRange componentRange = NSMakeRange(start, separatorRange.location - start);
        [components addObject:[self substringWithRange:componentRange]];
        start = NSMaxRange(separatorRange);
    }];
    [components addObject:[self substringFromIndex:start]];
    return components;
}

@end

你可以像这样使用它:

NSArray<NSString *> *inputs = @[@"bonus pay savings            2.69 F", @"brick and mortar             0.15-B"];
for (NSString *input in inputs) {
    NSArray<NSString *> *fields = [input componentsSeparatedByRegularExpressionPattern:@"\\s\\s+" error:nil];
    NSLog(@"fields: %@", fields);
}

输出:

2018-06-15 13:38:13.152725-0500 test[23423:1386429] fields: (
    "bonus pay savings",
    "2.69 F"
)
2018-06-15 13:38:13.153140-0500 test[23423:1386429] fields: (
    "brick and mortar",
    "0.15-B"
)

答案 2 :(得分:0)

如果您可以假设输入字符串中只有2个字段,我将使用有限的分割方法like this one,它始终返回2个项目的数组,然后使用“修剪”第二个项目的空格stringByTrimmingCharactersInSet

答案 3 :(得分:0)

@vadian和@robmayoff都提供了基于正则表达式(RE)的良好解决方案,在这两种情况下,RE都用于匹配 gap 以找到破坏字符串的位置。为了比较接近问题,另一种方法是使用RE来匹配您感兴趣的部分。 RE:

\S+(\h\S+)*

将匹配您感兴趣的文字,如下所示:

\S          - match any non-space character, \S excludes both horizontal
              (e.g. spaces, tabs) and vertical space (e.g. newlines)
\S+         - one or more non-space characters, i.e. a "word" of sorts
\h          - a single horizontal space character (if you wish matches to
              span lines use \s - any horizontal *or* vertical space)
\h\S+       - a space followed by a word
(\h\S+)*    - zero or more space separated words
\S+(\h\S+)* - a word follow by zero or more words

使用这个简单的正则表达式,您可以使用matchesInString:options:range:获取NSTextCheckingResult个对象的数组,每个对象输入一个;或者您可以使用enumerateMatchesInString:options:range:usingBlock:为每个匹配调用一个块。

以下是@ robmayoff方法的解决方案:

@interface NSString (componentsMatchingRegularExpression)

- (NSArray<NSString *>*) componentsMatchingRegularExpression:(NSString *)pattern;

@end

@implementation NSString (componentsMatchingRegularExpression)

- (NSArray<NSString *>*) componentsMatchingRegularExpression:(NSString *)pattern
{
   NSError *errorReturn;
   NSRegularExpression *regularExpression = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&errorReturn];

   if (!regularExpression)
      return nil;

   NSMutableArray *matches = NSMutableArray.new;
   [regularExpression enumerateMatchesInString:self
                                       options:0
                                         range:NSMakeRange(0, self.length)
                                    usingBlock:^(NSTextCheckingResult * _Nullable result, NSMatchingFlags flags, BOOL * _Nonnull stop)
                                              {
                                                 [matches addObject:[self substringWithRange:result.range]];
                                              }
   ];

   return matches.copy; // non-mutable copy
}

@end

是否匹配您希望保留或删除的内容更好是主观的,请选择。

答案 4 :(得分:0)

正则表达式很好,使用它们给出的解决方案也很好,但是为了完整起见,您也可以使用NSScanner做到这一点,NSScanner的性能几乎总是比正则表达式更好,并且习惯了如果需要执行更复杂的文本解析,请使用

NSString *str = @"bonus pay savings            2.69 F";
NSScanner *scanner = [NSScanner scannerWithString:str];
scanner.charactersToBeSkipped = nil; // default is to ignore whitespace
while (!scanner.isAtEnd) {
    NSString *name;
    NSString *value;
    // scan up to two spaces, this would be the name
    [scanner scanUpToString:@"  " intoString:&name];

    // scan the two spaces and any extra whitespace
    [scanner scanCharactersFromSet:[NSCharacterSet whitespaceCharacterSet] intoString:nil];

    // scan to the end of the line, this is the value
    [scanner scanUpToString:@"\n" intoString:&value];
}