Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Soulstorm

macrumors 68000
Original poster
Feb 1, 2005
1,887
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?
 

Soulstorm

macrumors 68000
Original poster
Feb 1, 2005
1,887
1
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?
 

HexMonkey

Administrator emeritus
Feb 5, 2004
2,240
504
New Zealand
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);
 

Soulstorm

macrumors 68000
Original poster
Feb 1, 2005
1,887
1
HexMonkey said:
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);
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!
 

caveman_uk

Guest
Feb 17, 2003
2,390
1
Hitchin, Herts, UK
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...
 

Soulstorm

macrumors 68000
Original poster
Feb 1, 2005
1,887
1
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$
 

caveman_uk

Guest
Feb 17, 2003
2,390
1
Hitchin, Herts, UK
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.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.