我有两个NSString
字符串,我想要找出它们之间的差异。
下面给一个例子:
NSString *pippo = @"pippo";
NSString *pippone = @"pippone";
我想获得两个实例中的不同字符,应该如何操作?
我有两个NSString
字符串,我想要找出它们之间的差异。
下面给一个例子:
NSString *pippo = @"pippo";
NSString *pippone = @"pippone";
我想获得两个实例中的不同字符,应该如何操作?
尽管一些特殊情况(例如后缀)可以使用更简单的算法处理,但为了处理一般情况,您可以:
1/ 首先提取一个公共序列。除非您的字符串非常长,否则最长公共子序列算法将是您的选择(LCS,请参见https://en.wikipedia.org/wiki/Longest_common_subsequence_problem)。
您可以在此处找到LCS的obj-c和swift实现:http://jakubturek.pl/blog/2015/06/27/using-swifts-string-type-with-care/
2/ 从LCS中获取差异很容易,例如请参见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", @""]];
你可以使用一些正则表达式:
我曾经编写过这个函数,可以将一个字符串中的另一个字符串替换为你想要的字符串/模式。
-(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”中找到的“pippo”,因此结果将是“ne”。
希望这可以帮助到你。
更新的答案:
-(void)getDifferenceBetweenString:(NSString *)firstString secondString:(NSString *)secondString{
NSString *longerString = @"";
NSString *shorterString = @"";
if (firstString.length >= secondString.length) {
longerString = firstString;
shorterString = secondString;
}else{
longerString = secondString;
shorterString = firstString;
}
NSArray *shorterArray = [self convertToArray:shorterString];
NSArray *longerArray = [self convertToArray:longerString];
NSMutableArray *differenceLettersArray = [NSMutableArray new];
for (NSString * letter in shorterArray) {
if (![longerString containsString:letter]) {
if (![differenceLettersArray containsObject:letter]) {
[differenceLettersArray addObject:letter];
}
}
}
for (NSString * letter in longerArray) {
if (![shorterString containsString:letter]) {
if (![differenceLettersArray containsObject:letter]) {
[differenceLettersArray addObject:letter];
}
}
}
NSLog(@"differences = %@",differenceLettersArray);
}
- (NSArray *)convertToArray:(NSString *)string {
NSMutableArray *arr = [[NSMutableArray alloc] init];
NSUInteger i = 0;
while (i < string.length) {
NSRange range = [string rangeOfComposedCharacterSequenceAtIndex:i];
NSString *chStr = [string substringWithRange:range];
[arr addObject:chStr];
i += range.length;
}
return arr;
}
然后按照以下方式使用:
[self getDifferenceBetweenString:@"pippo" secondString:@"pippone"];