在NSString

时间:2015-11-26 15:20:52

标签: ios objective-c nsstring substring nsrange

说我有一个包含以下数据的txt文件;

12345,123,98765,JOHN,RL,s/w
12345,123,98765,SAM,RL,s/w 
12345,123,98765,MIC,RL,s/w
12345,123,98765,MIC,RL,s/w
12345,123,98765,MIC,RL,s/w
12345,123,98765,MIC,RL,s/w
12345,123,98765,MIC,RL,s/w
12345,123,98765,AMI,RL,s/w
12345,123,98765,THIMOTHY,RL,s/w

它捆绑在我的应用程序中,我正在将数据读取到nsstring。我正在通过一个搜索词,比如'MIC'。当我通过这个搜索词时,我想获得具有搜索词的行并删除该字符串中的所有其他行。

我尝试过以下代码:

NSString *searchTerm = @"MIC";
    NSRange rangess = [dataToBeParsed rangeOfString:searchTerm];

    NSRange range = [dataToBeParsed rangeOfString:@"" options:NSBackwardsSearch range:rangess];
    NSLog(@"range.location: %lu", range.location);
    NSString *substring = [dataToBeParsed substringFromIndex:range.location+1];
    NSLog(@"substring: \n%@'", substring);

我能够找到搜索词的位置并清除字符串内容直到搜索位置。但我希望得到完整的一句话。

注意:在我的原始文档中,具有搜索字词的行将在文档中连续列出。

请帮忙。

2 个答案:

答案 0 :(得分:1)

NSString *string        = stringDataToBeParsed;
NSArray *components     = [string componentsSeparatedByString:@"\n"];
NSMutableArray *array   = [NSMutableArray new];

for (NSString *string in components)
{
    if ([string containsString:searchTerm])
    {
        [array addObject:string];
    }
}

NSString *stringWithSearchLinesOnly = [array componentsJoinedByString:@"\n"];

如果上述情况不够快,那么在Objective-c中你真的不会比这更快:

NSString *string             = stringDataToBeParsed;
NSMutableArray *mutableArray = [NSMutableArray new];

[string enumerateLinesUsingBlock:^(NSString * _Nonnull line, BOOL * _Nonnull stop)
{
    if ([line containsString:searchTerm])
    {
        [mutableArray addObject:line];
    }
}];

NSString *stringWithSearchLinesOnly = [mutableArray componentsJoinedByString:@"\n"];

答案 1 :(得分:0)

我认为有两件事会造成最大的代价:

  • 一次又一次地搜索整个字符串

  • 为部分字符串创建实例。

但是,您可以通过在整个字符串上使用范围而不是创建子字符串来摆脱它们:

NSUInteger length = [source length];
NSRange searchRange = NSMakeRange( 0, length );
NSRange hitRange = NSMakeRange( 0, 0 );

// Iterate over the string unless you do not find any hit
while( (hitRange = [source rangeOfString:@"Mic" options:0 range:searchRange]).length != 0)
{
   // hitRange contains the range we found "Mic". We have to enlarge it on both sides to \n
   NSRange lineRange = [source rangeOfString:@"\n" options:NSBackwardSearch range:NSMakeRange( 0, hitRange.location ); // Maybe it is an optimization to cut the range ahead of the hit to the last hit. But since it is a backward search, I do not think that this has any effect.

   // We can enlarge the range to the prev \n:
   hitRange.length = hitRange.range + hitRange.location - lineRange.location +1;

   // Go the the next \n
   lineRange = [source rangeOfString:@"\n" options:0 range:NSMakeRange( hitRange.location+hitRange.length, length-hitRange.location+hitRange.length)];

   hitRange.length = lineRange.location-hitRange.location;

   // Do something with the line
   …

   // Move forward
   searchRange.location = hitRange.location+hitRange.length;
   searchRange.length = length-searchRange.location;
}

键入Safari,只是为了显示方法。肯定会有+ 1 / -1错误和一些优化来减少对单个字符的搜索。

显然这只有作用,如果在结尾和开头有\ n。如果不是,请添加\ n。

我真的不知道,这是否更快。但是,值得一试。

作为一个补充,你可以在一个NSString的类别中创建一个方法,取一个占用范围的块。这会使它更通用。

修改后的代码:

NSUInteger length = [dataToBeParsedFirst length];
NSRange searchRange = NSMakeRange( 0, length );
NSRange hitRange = NSMakeRange( 0, 0 );
NSMutableArray *linesArr =[[NSMutableArray alloc]init];

// Iterate over the string unless you do not find any hit
while( (hitRange = [dataToBeParsedFirst rangeOfString:ItemID options:0 range:searchRange]).length != 0)
{
    NSRange lineRange = [dataToBeParsedFirst rangeOfString:@"\n" options:NSBackwardsSearch range:NSMakeRange( 0, hitRange.location )];

    NSRange lineEndRange = [dataToBeParsedFirst rangeOfString:@"\n" options:0 range:NSMakeRange(hitRange.location, 500)];

    NSRange dataRange = NSMakeRange(lineRange.location + lineRange.length, lineEndRange.location - lineRange.location + lineRange.length - 1);

    [linesArr addObject:[[dataToBeParsedFirst substringWithRange:dataRange] substringToIndex:dataRange.length - 1]];

    // Move forward
    searchRange.location = lineEndRange.location+lineEndRange.length;
    searchRange.length = length-searchRange.location;
}

NSString *dataToBeParsed = [[linesArr componentsJoinedByString:@"\n"] stringByAppendingString:@"\n"];