【问题标题】:Calculate number of differences between two NSStrings计算两个 NSString 之间的差异数
【发布时间】:2010-03-07 18:23:51
【问题描述】:

如何计算两个 NSString 之间的差异数。

例子:

NSString 1 = "this is a string"

NSString 2 = "Tihs isa string"

应该返回:4(一个用于大写“T”,一个用于“i”,“h”和缺失的空格)

【问题讨论】:

    标签: iphone nsstring comparison


    【解决方案1】:

    您正在寻找的是Levenshtein Distance

    Objective-C 中的实现:

    ------------------------------------------------------------------------ 
    
    //
    //  NSString-Levenshtein.h
    //
    //  Created by Rick Bourner on Sat Aug 09 2003.
    //  rick@bourner.com
    
    @interface NSString(Levenshtein)
    
    // calculate the smallest distance between all words in stringA and stringB
    - (float) compareWithString: (NSString *) stringB;
    
    // calculate the distance between two string treating them each as a
    // single word
    - (float) compareWithWord: (NSString *) stringB;
    
    // return the minimum of a, b and c
    - (int) smallestOf: (int) a andOf: (int) b andOf: (int) c;
    
    @end
    
    --------------------------------------------------------------------
    
    //
    //  NSString-Levenshtein.m
    //
    //  Created by Rick Bourner on Sat Aug 09 2003.
    //  Rick@Bourner.com
    
    #import "NSString-Levenshtein.h"
    
    
    @implementation NSString(Levenshtein)
    
    // calculate the mean distance between all words in stringA and stringB
    - (float) compareWithString: (NSString *) stringB
    {
         float averageSmallestDistance = 0.0;
         float smallestDistance;
         float distance;
    
         NSMutableString * mStringA = [[NSMutableString alloc]  initWithString: self];
         NSMutableString * mStringB = [[NSMutableString alloc]  initWithString: stringB];
    
    
         // normalize
         [mStringA replaceOccurrencesOfString:@"\n"
                                  withString: @" "
                                     options: NSLiteralSearch
                                       range: NSMakeRange(0, [mStringA  length])];
    
         [mStringB replaceOccurrencesOfString:@"\n"
                                  withString: @" "
                                     options: NSLiteralSearch
                                       range: NSMakeRange(0, [mStringB  length])];
    
         NSArray * arrayA = [mStringA componentsSeparatedByString: @" "];
         NSArray * arrayB = [mStringB componentsSeparatedByString: @" "];
    
         NSEnumerator * emuA = [arrayA objectEnumerator];
         NSEnumerator * emuB;
    
         NSString * tokenA = NULL;
         NSString * tokenB = NULL;
    
         // O(n*m) but is there another way ?!?
         while ( tokenA = [emuA nextObject] ) {
    
             emuB = [arrayB objectEnumerator];
             smallestDistance = 99999999.0;
    
             while ( tokenB = [emuB nextObject] )
                 if ( (distance = [tokenA compareWithWord: tokenB] ) <  smallestDistance )
                     smallestDistance = distance;
    
             averageSmallestDistance += smallestDistance;
    
         }
    
         [mStringA release];
         [mStringB release];
    
         return averageSmallestDistance / [arrayA count];
    }
    
    
    // calculate the distance between two string treating them eash as a
    // single word
    - (float) compareWithWord: (NSString *) stringB
    {
         // normalize strings
         NSString * stringA = [NSString stringWithString: self];
         [stringA stringByTrimmingCharactersInSet:
                   [NSCharacterSet whitespaceAndNewlineCharacterSet]];
         [stringB stringByTrimmingCharactersInSet:
                   [NSCharacterSet whitespaceAndNewlineCharacterSet]];
         stringA = [stringA lowercaseString];
         stringB = [stringB lowercaseString];
    
    
         // Step 1
         int k, i, j, cost, * d, distance;
    
         int n = [stringA length];
         int m = [stringB length];  
    
         if( n++ != 0 && m++ != 0 ) {
    
             d = malloc( sizeof(int) * m * n );
    
             // Step 2
             for( k = 0; k < n; k++)
                 d[k] = k;
    
             for( k = 0; k < m; k++)
                 d[ k * n ] = k;
    
             // Step 3 and 4
             for( i = 1; i < n; i++ )
                 for( j = 1; j < m; j++ ) {
    
                     // Step 5
                     if( [stringA characterAtIndex: i-1] == 
                          [stringB characterAtIndex: j-1] )
                         cost = 0;
                     else
                         cost = 1;
    
                     // Step 6
                     d[ j * n + i ] = [self smallestOf: d [ (j - 1) * n + i ] + 1
                                                 andOf: d[ j * n + i - 1 ] +  1
                                                 andOf: d[ (j - 1) * n + i -1 ] + cost ];
                 }
    
             distance = d[ n * m - 1 ];
    
             free( d );
    
             return distance;
         }
         return 0.0;
    }
    
    
    // return the minimum of a, b and c
    - (int) smallestOf: (int) a andOf: (int) b andOf: (int) c
    {
         int min = a;
         if ( b < min )
             min = b;
    
         if( c < min )
             min = c;
    
         return min;
    }
    
    @end
    

    以上来源作者:Rick Bourner,http://www.merriampark.com/ldobjc.htm

    【讨论】:

    • 我一点也不知道!我发布了 Objective-C 代码,因为 (1) 我认为那是您正在使用的语言,以及 (2) 代码来自 merriampark.com,使其(恕我直言)成为可靠的来源。就我个人而言,我对编写 iPhone 应用程序的语言没有经验。但是算法和伪代码应该足以让你暂时完成工作,对吧?
    • 这是 NSString 上的一个类别,所以如果你把它放在适当的头文件和实现文件中,然后包含头文件,你应该可以做到 [string1 compareWithString:string1]。
    • @brad 这就是我的想法,但浮动让我措手不及
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-13
    • 1970-01-01
    • 1970-01-01
    • 2021-07-16
    相关资源
    最近更新 更多