Cocoa:NSString Search Methods Question

Discussion in 'Mac Programming' started by Soulstorm, Jul 3, 2006.

  1. macrumors 68000

    Soulstorm

    Joined:
    Feb 1, 2005
    #1
    I have an NSArray which holds NSString objects.

    I want to write a search method that will return similar (NOT exact) matches of a given NSStsing.

    For example I want the search for "Nick" to return results for "Nickolas", "Nickolette", "Parnickette", etc.

    I am having difficulties to do that because by looking at Apple's documentation, NSString doesn't seem to have such a comparison function. Can anyone tell me how to do this?
     
  2. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #2
    I'd use one of the available regexp libraries.
     
  3. thread starter macrumors 68000

    Soulstorm

    Joined:
    Feb 1, 2005
    #3
    I can't even read the first one. It's written in Japanese. And the second one concerns PHP.

    Isn't there any way to do this using plain Cocoa?
     
  4. Administrator

    HexMonkey

    Staff Member

    Joined:
    Feb 5, 2004
    Location:
    New Zealand
    #4
    You can use rangeOfString to check if a string contains another, which would result in a match for all your examples. For example:

    Code:
    BOOL match = ([aString rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location != NSNotFound);
     
  5. thread starter macrumors 68000

    Soulstorm

    Joined:
    Feb 1, 2005
    #5
    Simple and fast. Thanks a lot, that worked out quite nicely.

    Also, robbieduncan, I hadn't looked well the link you gave me. Although my problem has been solved, you have given me a good starting point for other things, thanks a lot!
     
  6. Guest

    caveman_uk

    Joined:
    Feb 17, 2003
    Location:
    Hitchin, Herts, UK
    #6
    If you need rather more than 'is this a substring of this string' then there are a range of algorithms you can use. I implemented one of them in my program that gives a similarity score based on adjacent letter pairs and it seems to work pretty well. If you're interested I can post it...
     
  7. thread starter macrumors 68000

    Soulstorm

    Joined:
    Feb 1, 2005
    #7
    Any code resource would be nice, caveman. If you want, I am interested in seeing the code.

    BTW, has anyone been able to compile the Omnigroup's Foundation sourcecode on his/her Mac? When I try to do it, I always end up in an error in the terminal, like this:

    Code:
    /Users/soulstorm/Desktop/OmniGroup/Frameworks/OmniFoundation/Tests/OFSetTests.m: In function '-[OFSetTests testSetFromArray]':
    /Users/soulstorm/Desktop/OmniGroup/Frameworks/OmniFoundation/Tests/OFSetTests.m:33: warning: implicit declaration of function 'shouldBeEqual'
    
    Ld /Users/Shared/soulstorm/Products/Debug/OFUnitTests.otest/Contents/MacOS/OFUnitTests normal ppc
        cd /Users/soulstorm/Desktop/OmniGroup/Frameworks/OmniFoundation
        /usr/bin/gcc-4.0 -o /Users/Shared/soulstorm/Products/Debug/OFUnitTests.otest/Contents/MacOS/OFUnitTests -L/Users/Shared/soulstorm/Products/Debug -F/Users/Shared/soulstorm/Products/Debug -F/Developer/SDKs/MacOSX10.4u.sdk/Library/Frameworks -filelist /Users/soulstorm/xcode/intermediate\ files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFUnitTests.LinkFileList -framework OmniBase -framework Foundation -framework SenTestingKit -framework OmniFoundation -arch ppc -Wl,-Y,1455 -bundle -mmacosx-version-min=10.3 -isysroot /Developer/SDKs/MacOSX10.4u.sdk
    /usr/bin/ld: Undefined symbols:
    _should
    _shouldBeEqual
    _fail1
    _shouldBeEqual1
    _should1
    _shouldnt
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFXMLDocumentTests.o reference to undefined _should
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFXMLDocumentTests.o reference to undefined _shouldBeEqual
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFDateTestCase.o reference to undefined _fail1
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFDateTestCase.o reference to undefined _shouldBeEqual1
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFHeapTests.o reference to undefined _should
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFHeapTests.o reference to undefined _shouldBeEqual
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFBTreeTest.o reference to undefined _should
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFBTreeTest.o reference to undefined _should1
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFRegexpTests.o reference to undefined _should
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFRegexpTests.o reference to undefined _should1
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFRegexpTests.o reference to undefined _shouldBeEqual
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFHashTests.o reference to undefined _should
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFHashTests.o reference to undefined _shouldBeEqual
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFStringEncodingTests.o reference to undefined _should
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFStringEncodingTests.o reference to undefined _shouldBeEqual
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFStringEncodingTests.o reference to undefined _shouldBeEqual1
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFXMLCursorTests.o reference to undefined _should
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFXMLCursorTests.o reference to undefined _shouldBeEqual
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFArrayTests.o reference to undefined _should
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFArrayTests.o reference to undefined _should1
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFArrayTests.o reference to undefined _shouldBeEqual
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFArrayTests.o reference to undefined _shouldnt
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFSearchingTests.o reference to undefined _should
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFSearchingTests.o reference to undefined _should1
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFSearchingTests.o reference to undefined _shouldBeEqual
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFSearchingTests.o reference to undefined _shouldnt
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFNumberFormatterTest.o reference to undefined _should
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFNumberFormatterTest.o reference to undefined _shouldBeEqual
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFStringScannerTest.o reference to undefined _should
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFStringScannerTest.o reference to undefined _shouldBeEqual
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFStringScannerTest.o reference to undefined _shouldnt
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFAliasTests.o reference to undefined _should
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFAliasTests.o reference to undefined _shouldBeEqual
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFCompressionTest.o reference to undefined _should
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFCompressionTest.o reference to undefined _shouldBeEqual
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFStringExtensionsTest.o reference to undefined _should
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFStringExtensionsTest.o reference to undefined _should1
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFStringExtensionsTest.o reference to undefined _shouldBeEqual
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFMutableAttributedStringExtensionsTest.o reference to undefined _should
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFMutableAttributedStringExtensionsTest.o reference to undefined _shouldBeEqual
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFVersionNumberTests.o reference to undefined _should
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFVersionNumberTests.o reference to undefined _shouldBeEqual
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFAttributedStringExtensionsTest.o reference to undefined _shouldBeEqual
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFTimeSpanFormatterTest.o reference to undefined _should
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFErrorExtensionTests.o reference to undefined _should
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFErrorExtensionTests.o reference to undefined _shouldBeEqual
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFErrorExtensionTests.o reference to undefined _shouldnt
    /Users/soulstorm/xcode/intermediate files/OmniFoundation.build/Debug/OFUnitTests.build/Objects-normal/ppc/OFSetTests.o reference to undefined _shouldBeEqual
    collect2: ld returned 1 exit status
    ** BUILD FAILED **
    Build failed in  (OmniGroup/Frameworks/OmniFoundation(OFUnitTests))
    G5:~/Desktop/OmniGroup soulstorm$ 
     
  8. Guest

    caveman_uk

    Joined:
    Feb 17, 2003
    Location:
    Hitchin, Herts, UK
    #8
    OK then, here you go. It's a category on NSString. The actual method to use is
    Code:
    -(float) similarityWithString:(NSString*) otherString;
    
    It returns a float between 0 and 1.0 with better matches being nearer 1.0.

    NSStringExtensions.h
    Code:
    #import <Cocoa/Cocoa.h>
    
    @interface NSString (NSStringExtensions)
    
    -(float) similarityWithString:(NSString*) otherString;
    
    -(NSMutableArray*) _letterPairs:(NSString*) string;
    
    -(NSMutableArray*) _wordLetterPairs:(NSString*) string;
    
    @end
    
    NSStringExtensions.m
    Code:
    #import "NSStringExtensions.h"
    
    @implementation NSString (NSStringExtensions)
    
    -(float) similarityWithString:(NSString*) otherString;
    {
    	NSMutableArray* pairs1=[self _wordLetterPairs:[self uppercaseString]];
    	NSMutableArray* pairs2=[otherString _wordLetterPairs:[otherString uppercaseString]];
    	
    	int intersection=0;
    	int u=([pairs1 count]+[pairs2 count]);
    	int i=0;
    	int j;
    	for (; i<[pairs1 count]; i++)
    	{
    		j=0;
    		for (; j<[pairs2 count]; j++)
    		{
    			if ([[pairs1 objectAtIndex:i] isEqualTo:[pairs2 objectAtIndex:j]])
    			{
    				intersection++;
    				[pairs2 removeObjectAtIndex:j];
    			}
    		}
    	}
    	return (2.0*intersection)/u;
    }
    
    -(NSMutableArray*) _letterPairs:(NSString*) string;
    {
    	int numPairs=[string length]-1;
    	NSMutableArray* pairs=[NSMutableArray arrayWithCapacity:numPairs];
    	
    	int i=0;
    	for (;i<numPairs; i++)
    		[pairs addObject:[string substringWithRange:NSMakeRange(i,2)]];
    	return pairs;
    }
    
    -(NSMutableArray*) _wordLetterPairs:(NSString*) string;
    {
    	NSMutableArray* allPairs=[NSMutableArray array];
    	NSArray* words=[string componentsSeparatedByString:@" "];
    	int w=0;
    	for (; w<[words count]; w++)
    		[allPairs addObjectsFromArray:[self _letterPairs:[words objectAtIndex:w]]];
    	return allPairs;
    }
    
    @end
    
    This code is my attempt at an objective-C version of the method and example code presented here.
     

Share This Page