2013-05-12 9 views
3

У меня есть два NSString и я хочу получить разницу между ними.Получение различий между двумя NSStrings

Позвольте мне привести пример:

NSString *pippo = @"pippo"; 
NSString *pippone = @"pippone"; 

Я хотел бы получить различные символы в этих двух случаях. Как я могу это сделать?

+3

Я начал набирать ответ на ваш вопрос, а затем понял, чтобы дать лучший ответ, нужно было бы узнать немного более подробно. Например, если строка первая - «мясо», а другая - «пряный фрикадель», вы хотите, чтобы разница была «пряным мячиком» или буквами, отличными между предложениями, например. {С, р, я, с, у, б, л}? –

+3

Как вы определяете разницу между строками? Всегда ли это так, как вы здесь выразились, где одна строка имеет дополнительные символы в конце? Или, например, как вы считаете разницу между _pippo_ и _pissone_? – FluffulousChimp

+0

Возможный дубликат [Проверить, являются ли два NSStrings похожими] (http://stackoverflow.com/questions/12984442/check-if-two-nsstrings-are-similar) –

ответ

0

Вы можете использовать некоторые Regex:

Я сделал эту функцию один раз, чтобы заменить строку в другую строку по строке/шаблон вы хотите.

-(NSString *)replaceInString:(NSString *)chaine :(NSString *)pattern 
      :(NSString *)template 
{ 
NSMutableString *chaineMutable = [[NSMutableString alloc] initWithString:chaine]; 
NSRegularExpression *regex = [[NSRegularExpression alloc] init]; 

regex = [NSRegularExpression regularExpressionWithPattern:pattern 
      options:NSRegularExpressionCaseInsensitive error:NULL]; 

[regex replaceMatchesInString:(NSMutableString *)chaineMutable 
      options:NSMatchingReportProgress range:NSMakeRange(0, [chaine length]) 
      withTemplate:template]; 

NSString *returnedString = [[NSString alloc] initWithString:chaineMutable]; 

return returnedString; 
} 

Тогда можно назвать:

NSString *difference = [self replaceInString:pippone :pippo :@""]; 

Таким образом, вы будете заменить "Пиппо" найдено в "pippone" на "" (ничего), так что результат будет "пе".

Надеюсь, что это поможет.

+0

Он работает, если символ разности находится в конце или в start, но он не дает diff char, если он находится в середине, например, если chaine = @ "pippone" и pattern = @ "pipone", то он не может дать разницу как: p is diff –

-2

Попробуйте этот метод я сделал для вас и его работы 100%:

NSString *pippone = @"pippone"; 
NSString *pippo = @"pippo"; 
NSString *finalSTR = @""; 
if ([pippone length]>[pippo length]) { 
    NSCharacterSet *doNotWant = [NSCharacterSet characterSetWithCharactersInString:pippo]; 
    finalSTR = [[pippone componentsSeparatedByCharactersInSet: doNotWant] componentsJoinedByString: @""]; 
} 
else{ 
    NSCharacterSet *doNotWant = [NSCharacterSet characterSetWithCharactersInString:pippone]; 
    finalSTR = [[pippo componentsSeparatedByCharactersInSet: doNotWant] componentsJoinedByString: @""]; 

} 
NSLog(@"%@", finalSTR); 
2

Хотя несколько особых случаев (например, суффиксов) может быть обработано с более простыми алгоритмами, ро обрабатывать общий случай, вы можете:

1/сначала выведите общую последовательность. Если ваша строка не очень длинная, вам будет предложен самый длинный общий алгоритм подпоследовательности (LCS, см. https://en.wikipedia.org/wiki/Longest_common_subsequence_problem).

Вы можете найти Obj-C и быстрой реализации ЛВП здесь: http://jakubturek.pl/blog/2015/06/27/using-swifts-string-type-with-care/

2/с ЛВП, легко получить и переформатирование, смотри, например, https://en.wikipedia.org/wiki/Diff_utility, например. Ниже в реализации Obj-C (категории NSString, предполагая, что мы имеем longestCommonSubsequence: из приведенной выше ссылке):

- (NSArray *) lcsDiff:(NSString *)string 
{ 
    NSString *lcs = [self longestCommonSubsequence:string]; 
    NSUInteger l1 = [self length]; 
    NSUInteger l2 = [string length]; 
    NSUInteger lc = [lcs length]; 
    NSUInteger idx1 = 0; 
    NSUInteger idx2 = 0; 
    NSUInteger idxc = 0; 
    NSMutableString *s1 = [[NSMutableString alloc]initWithCapacity:l1]; 
    NSMutableString *s2 = [[NSMutableString alloc]initWithCapacity:l2]; 
    NSMutableArray *res = [NSMutableArray arrayWithCapacity:10]; 
    for (;;) { 
     if (idxc >= lc) break; 
     unichar c1 = [self characterAtIndex:idx1]; 
     unichar c2 = [string characterAtIndex:idx2]; 
     unichar cc = [lcs characterAtIndex:idxc]; 
     if ((c1==cc) && (c2 == cc)) { 
      if ([s1 length] || [s2 length]) { 
       NSArray *e = @[ s1, s2]; 
       [res addObject:e]; 
       s1 = [[NSMutableString alloc]initWithCapacity:l1]; 
       s2 = [[NSMutableString alloc]initWithCapacity:l1]; 
      } 
      idx1++; idx2++; idxc++; 
      continue; 
     } 
     if (c1 != cc) { 
      [s1 appendString:[NSString stringWithCharacters:&c1 length:1]]; 
      idx1++; 
     } 
     if (c2 != cc) { 
      [s2 appendString:[NSString stringWithCharacters:&c2 length:1]]; 
      idx2++; 
     } 
    } 
    if (idx1<l1) { 
     [s1 appendString:[self substringFromIndex:idx1]]; 
    } 
    if (idx2<l2) { 
     [s2 appendString:[string substringFromIndex:idx2]]; 
    } 
    if ([s1 length] || [s2 length]) { 
     NSArray *e = @[ s1, s2]; 
     [res addObject:e]; 
    } 
    return res; 
} 

код возвращает массив с одним элементом (string1, string2) для каждой разности между двумя строками , например [@ "abcXefY" lcsDiff: @ "aZbcKef"] вернется @[ @[ @"", @"Z"], @[ @"X", @"K"], @[ @"Y", @""]];

+0

Спасибо! Хорошо работает с версией Swift 2.2 с наиболее длинной общей подпоследовательностью из [здесь] (https://rosettacode.org/wiki/Longest_common_subsequence#Swift). Приятный пример самой длинной общей подстроки в Objective-C можно найти здесь [https: //en.wikibooks.орг/вики/Algorithm_Implementation/Струны/Longest_common_substring # Objective-C) – Lion

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