2015-11-26 2 views
0

say У меня есть txt-файл с данными следующим образом;Поиск положения символа, связанного с положением другого символа в NSString

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); 

Я смог найти местоположение поискового термина и очистить содержимое строки до поиска местоположения. Но я хочу получить полную строку.

Примечание: В моем исходном документе строки, содержащие поисковый запрос, будут отображаться постоянно, как в документе.

Пожалуйста, помогите.

+1

Держа его в строке не является правильным. Вам нужен массив из массива строк. – trojanfoe

+1

Вы можете использовать регулярное выражение: '^ (. * (?: MIC). *) $'. Просто замените «MIC» тем, что вы хотите найти. Оценка этого выражения даст вам полные строки. – akashivskyy

+0

Как сказал @trojanfoe, лучше использовать NSArray из NSArray, особенно когда CSV представляется «с запятой в качестве разделителя». – Larme

ответ

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"]; 
+0

Большое вам спасибо @amin. Это то, что я пытался сделать. Я сделал несколько изменений в коде, и он работал так, как я ожидал! :) Раньше для завершения операции поиска потребовалось около 15 секунд. Теперь это занимает всего 8 секунд! ! – Mithun

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"]; 
+0

Спасибо за ответ. Я пробовал этот метод, но проблема в том, что, поскольку в файле csv больше двух строк, для циклирования всех этих строк требуется больше времени. – Mithun

+0

См. Обновленный ответ. – TheBasicMind

+0

Так мы и закончили. Чтобы завершить операцию, потребовалось около 15 секунд. – Mithun

Смежные вопросы