簡體   English   中英

如何在發現兩個或更多空白字符的地方拆分NSString?

[英]How to split NSString where two or more whitespace characters are found?

給定的字符串輸入:

@"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個空格作為分隔符,而空格的數量可以變化。 如何做到這一點? 謝謝。

使用正則表達式的簡單解決方案。

它用隨機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);

您可以使用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個字段,那么我將使用這種有限的拆分方法,該方法始終返回2個項目的數組,然后使用stringByTrimmingCharactersInSet來 “修剪”第二個項目。

@vadian和@robmayoff雙雙提供基於正則表達式(RES)好的解決辦法,在這兩種情況下的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對象數組, 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

是否匹配您希望保留或刪除的內容比較主觀,請選擇。

正則表達式對此很合適,使用它們給出的解決方案也非常合適,但是對於完成而言,您也可以使用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];
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM