Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added StringScore library from previous project. Updated readme

  • Loading branch information...
commit 13b0f1cdb3f20c5e6457eac77b19e423358a77f4 1 parent 1a4e6a6
Nicholas Bruning authored
Showing with 224 additions and 3 deletions.
  1. +24 −0 NSString+Score.h
  2. +123 −0 NSString+Score.m
  3. +77 −3 README.md
24 NSString+Score.h
View
@@ -0,0 +1,24 @@
+//
+// NSString+Score.h
+//
+// Created by Nicholas Bruning on 5/12/11.
+// Copyright (c) 2011 Involved Pty Ltd. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+enum{
+ NSStringScoreOptionNone = 1 << 0,
+ NSStringScoreOptionFavorSmallerWords = 1 << 1,
+ NSStringScoreOptionReducedLongStringPenalty = 1 << 2
+};
+
+typedef NSUInteger NSStringScoreOption;
+
+@interface NSString (Score)
+
+- (CGFloat) scoreAgainst:(NSString *)otherString;
+- (CGFloat) scoreAgainst:(NSString *)otherString fuzziness:(NSNumber *)fuzziness;
+- (CGFloat) scoreAgainst:(NSString *)otherString fuzziness:(NSNumber *)fuzziness options:(NSStringScoreOption)options;
+
+@end
123 NSString+Score.m
View
@@ -0,0 +1,123 @@
+//
+// NSString+Score.m
+//
+// Created by Nicholas Bruning on 5/12/11.
+// Copyright (c) 2011 Involved Pty Ltd. All rights reserved.
+//
+
+//score reference: http://jsfiddle.net/JrLVD/
+
+#import "NSString+Score.h"
+
+@implementation NSString (Score)
+
+- (CGFloat) scoreAgainst:(NSString *)otherString{
+ return [self scoreAgainst:otherString fuzziness:nil];
+}
+
+- (CGFloat) scoreAgainst:(NSString *)otherString fuzziness:(NSNumber *)fuzziness{
+ return [self scoreAgainst:otherString fuzziness:fuzziness options:NSStringScoreOptionNone];
+}
+
+- (CGFloat) scoreAgainst:(NSString *)otherString fuzziness:(NSNumber *)fuzziness options:(NSStringScoreOption)options{
+ // If the string is equal to the abbreviation, perfect match.
+ if([self isEqualToString:otherString]) return (CGFloat) 1.0f;
+
+ //if it's not a perfect match and is empty return 0
+ if([otherString length] == 0) return (CGFloat) 0.0f;
+
+ CGFloat totalCharacterScore = 0;
+ NSUInteger otherStringLength = [otherString length];
+ NSString *string = self;
+ NSUInteger stringLength = [string length];
+ BOOL startOfStringBonus = NO;
+ CGFloat otherStringScore;
+ CGFloat fuzzies = 1;
+ CGFloat finalScore;
+
+ // Walk through abbreviation and add up scores.
+ for(uint index = 0; index < otherStringLength; index++){
+ CGFloat characterScore = 0.1;
+ NSInteger indexInString = NSNotFound;
+ NSString *chr;
+ NSRange rangeChrLowercase;
+ NSRange rangeChrUppercase;
+
+ chr = [otherString substringWithRange:NSMakeRange(index, 1)];
+
+ //make these next few lines leverage NSNotfound, methinks.
+ rangeChrLowercase = [string rangeOfString:[chr lowercaseString]];
+ rangeChrUppercase = [string rangeOfString:[chr uppercaseString]];
+
+ if(rangeChrLowercase.location == NSNotFound && rangeChrUppercase.location == NSNotFound){
+ if(fuzziness){
+ fuzzies += 1 - [fuzziness floatValue];
+ } else {
+ return 0;
+ }
+ } else if(rangeChrLowercase.location == NSNotFound || rangeChrUppercase.location == NSNotFound){
+ indexInString = rangeChrLowercase.location != NSNotFound ? rangeChrLowercase.location : rangeChrUppercase.location;
+ } else {
+ indexInString = MIN(rangeChrLowercase.location, rangeChrUppercase.location);
+ }
+
+ // Set base score for matching chr
+
+ // Same case bonus.
+ if(indexInString != NSNotFound && [[string substringWithRange:NSMakeRange(indexInString, 1)] isEqualToString:chr]){
+ characterScore += 0.1;
+ }
+
+ // Consecutive letter & start-of-string bonus
+ if(indexInString == 0){
+ // Increase the score when matching first character of the remainder of the string
+ characterScore += 0.6;
+ if(index == 0){
+ // If match is the first character of the string
+ // & the first character of abbreviation, add a
+ // start-of-string match bonus.
+ startOfStringBonus = YES;
+ }
+ } else {
+ // Acronym Bonus
+ // Weighing Logic: Typing the first character of an acronym is as if you
+ // preceded it with two perfect character matches.
+ if( [[string substringWithRange:NSMakeRange(indexInString - 1, 1)] isEqualToString:@" "] ){
+ characterScore += 0.8;
+ }
+ }
+
+ // Left trim the already matched part of the string
+ // (forces sequential matching).
+ string = [string substringFromIndex:indexInString + 1];
+
+ totalCharacterScore += characterScore;
+ }
+
+ if(NSStringScoreOptionFavorSmallerWords == (options & NSStringScoreOptionFavorSmallerWords)){
+ // Weigh smaller words higher
+ return totalCharacterScore / stringLength;
+ }
+
+ otherStringScore = totalCharacterScore / otherStringLength;
+
+ if(NSStringScoreOptionReducedLongStringPenalty == (options & NSStringScoreOptionReducedLongStringPenalty)){
+ // Reduce the penalty for longer words
+ CGFloat percentageOfMatchedString = otherStringLength / stringLength;
+ CGFloat wordScore = otherStringScore * percentageOfMatchedString;
+ finalScore = (wordScore + otherStringScore) / 2;
+
+ } else {
+ finalScore = ((otherStringScore * ((CGFloat)(otherStringLength) / (CGFloat)(stringLength))) + otherStringScore) / 2;
+ }
+
+ finalScore = finalScore / fuzzies;
+
+ if(startOfStringBonus && finalScore + 0.15 < 1){
+ finalScore += 0.15;
+ }
+
+ return finalScore;
+}
+
+@end
80 README.md
View
@@ -1,4 +1,78 @@
-StringScore
-===========
+# StringScore
-StringScore is an Objective-C library which provides super fast fuzzy string matching/scoring. Based on the same javascript library which powers Github's filename string matching.
+StringScore is an Objective-C library which provides super fast fuzzy string matching/scoring. Based on the [JavaScript library of the same name](https://github.com/joshaven/string_score), by [Joshaven Potter](https://github.com/joshaven).
+
+
+## Using StringScore
+
+StringScore adds 3 new methods to `NSString`:
+
+````
+- (CGFloat) scoreAgainst:(NSString *)otherString;
+
+- (CGFloat) scoreAgainst:(NSString *)otherString fuzziness:(NSNumber *)fuzziness;
+
+- (CGFloat) scoreAgainst:(NSString *)otherString fuzziness:(NSNumber *)fuzziness options:(NSStringScoreOption)options;
+````
+
+All three methods return a `CGFloat` representing how closely the string
+matched the `otherString` parameter.
+
+
+## Additional Parameters
+
+### Fuzziness
+
+A number between 0 and 1 which varys how fuzzy/ the calculation is.
+Defaults to `nil` (fuzziness disabled).
+
+
+### Options
+
+There are 3 options available: `NSStringScoreOptionNone`, `NSStringScoreOptionFavorSmallerWords` and `NSStringScoreOptionReducedLongStringPenalty`. Each of which is pretty self-explanatory, see example below for usage.
+
+
+## Examples
+
+Given the following sample application:
+
+````
+NSString *testString = @"Hello world!";
+
+CGFloat result1 = [testString scoreAgainst:@"Hello world!"];
+CGFloat result2 = [testString scoreAgainst:@"world"];
+CGFloat result3 = [testString scoreAgainst:@"wXrld" fuzziness:[NSNumber numberWithFloat:0.8]];
+CGFloat result4 = [testString scoreAgainst:@"world" fuzziness:nil options:NSStringScoreOptionFavorSmallerWords];
+CGFloat result5 = [testString scoreAgainst:@"world" fuzziness:nil options:(NSStringScoreOptionFavorSmallerWords & NSStringScoreOptionReducedLongStringPenalty)];
+CGFloat result6 = [testString scoreAgainst:@"HW"]; // abbreviation matching example
+
+NSLog(@"Result 1 = %f", result1);
+NSLog(@"Result 2 = %f", result2);
+NSLog(@"Result 3 = %f", result3);
+NSLog(@"Result 4 = %f", result4);
+NSLog(@"Result 5 = %f", result5);
+NSLog(@"Result 6 = %f", result6);
+````
+
+The resulting output is:
+
+````
+2012-05-14 15:13:38.074 StringScore[13415:18a03] Result 1 = 1.000000
+2012-05-14 15:13:38.075 StringScore[13415:18a03] Result 2 = 0.425000
+2012-05-14 15:13:38.075 StringScore[13415:18a03] Result 3 = 0.271528
+2012-05-14 15:13:38.076 StringScore[13415:18a03] Result 4 = 0.250000
+2012-05-14 15:13:38.077 StringScore[13415:18a03] Result 5 = 0.425000
+2012-05-14 15:13:38.078 StringScore[13415:18a03] Result 6 = 0.645833
+````
+
+## Credits
+
+Author: [Nicholas Bruning](https://github.com/thetron)
+
+Special thanks to [Joshaven Potter](https://github.com/joshaven) for
+providing the basis for this library.
+
+
+## License
+
+Licensed under the [MIT license](http://www.opensource.org/licenses/mit-license.php).
Please sign in to comment.
Something went wrong with that request. Please try again.