Question

I have an NSArray of alphabetical codes which I would like to sort. Let say: @[ABC,DEF,GHI,JKL]

When the user types in the search phrase JKL I would like to sort the array in way that the entry JKL is listed first. You could say the array should be sorted matching the search string the closest.

I have tried using NSSortDescriptor but haven't got very far with that. The crux here is it's sorting alphabetically.

Here is my code:

NSSortDescriptor *code;
code = [[NSSortDescriptor alloc] initWithKey:@"code" ascending:YES selector:@selector(localizedStandardCompare:)];

NSArray *sortDescriptors = [NSArray arrayWithObjects:code, nil];

NSArray *sortedArray;
sortedArray = [matches sortedArrayUsingDescriptors:sortDescriptors];

NSArray *matches = [NSArray arrayWithArray: sortedArray];

Any help getting me in the right direction would be greatly appreciated! Thanks a lot.

Was it helpful?

Solution

You need to define what it means to "sort matching the search string the closest". If you can define an algorithm for closeness to an arbitrary search string then you can implement a search block/selector that you could use to sort the array into "closest to search string" order.

EDIT:

You could sort your strings based on their alphabetic distance from your match string. That would be odd, however, since if your search string is "jjj" and your list is "aaa" "bbb" "iii" "jjj" "kkk" "yyy" "zzz" your result array would be

"jjj" "kkk" "iii" "yyy" "bbb" "zzz" "aaa"

The results would not be in alphabetical order at all, but rather in order based on how close they fall alphabetically to your match string.

To do that sort, you'd need a way to represent each string numerically.

Off the top of my head, here's how I would do that:

convert each letter to a value 1-26 (a=1, z=26)

Start with a value of zero.

For the first letter, add it's value to the string value

For the second letter, add letter_value X 26^-1 (letter value times 26 to the minus 1 power) For the third letter, add letter_value X 26^-2

And so on.

That would add increasingly smaller values for each digit.

Now build an array of objects that contain both the string and the absolute value of the difference between each string and your match string

Now sort the array based on it's "distance" value.

Since this method uses fractional exponents to calculate values it would be slow to come up with the sort keys, but it should work

OTHER TIPS

I'm not sure exactly what you are after, but you state that sorting alphabetically is crucial - so here is how to sort an array alphabetically:

NSArray *codes = @[@"DEF", @"ABC", @"GHI", @"JKL"];
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:@"self" ascending:YES];  // use ascending:NO for reverse alpha sorting
NSArray *sortedCodes = [codes sortedArrayUsingDescriptors:@[descriptor]];

If you are trying to find the 'closest matches' to an object, you may wish to try NSPredicate with Eg:

NSString *searchString = @"XYZ";
NSArray *searchOptions =@[@"WXY", @"WXYZ", @"XYZ", @"XYZA", @"ZYA"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self CONTAINS[c] %@", searchString];
NSArray *containsMatches = [searchOptions filteredArrayUsingPredicate:predicate];
NSLog(@"closest search matches: %@", containsMatches);
// returns WXYZ, XYZ, XYZA

The [c] means case-insensitive. String comparisons in a predicate include:

BEGINSWITH
  The left-hand expression begins with the right-hand expression.
CONTAINS
  The left-hand expression contains the right-hand expression.
ENDSWITH
  The left-hand expression ends with the right-hand expression.
LIKE
  The left hand expression equals the right-hand expression: ? and * are allowed as wildcard characters, where ? matches 1 character and * matches 0 or more characters.
MATCHES
  The left hand expression equals the right hand expression using a regex-style comparison according to ICU v3 (for more details see the ICU User Guide for Regular Expressions).

See Apple Docs for more info on NSPredicates: https://developer.apple.com/library/mac/documentation/cocoa/conceptual/predicates/Articles/pSyntax.html#//apple_ref/doc/uid/TP40001795-SW1

Perhaps a combination of NSPredicate and NSSortDescriptor may achieve your goal?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top