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

i.yalovecky

macrumors member
Original poster
Feb 24, 2010
67
0
subj

resulted order must be
1.0.0a3
1.0.0b4
1.0.0b11

NSString compare:str options:NSNumericSearch

gives another order
1.0.0a3
1.0.0b11
1.0.0b4
 
You'll have to define your own custom comparator that understands the different components of the numbers (version numbers?).
 
You'll have to define your own custom comparator that understands the different components of the numbers (version numbers?).

It looks right. But i thought that so usual task already implemented in one of the base frameworks.
 
Learn how to use NSScanner to scanUpToCharactersInSet:[NSCharacterSet decimalDigitCharacterSet], followed by -scanInt:
 
subj

resulted order must be
1.0.0a3
1.0.0b4
1.0.0b11

NSString compare:str options:NSNumericSearch

gives another order
1.0.0a3
1.0.0b11
1.0.0b4

This is supposed to work, for example creating three folders with these names in the Finder will sort them correctly. I'd check my code carefully. What happens if you sort "1", "5" and "23" with the same code?
 
Post your code, and identify your OS version.

The following works wherever I try it:
Code:
#import <Foundation/Foundation.h>

NSComparisonResult versionCompare( id str1, id str2, void *context )
{
	return [str1 compare:str2 options:NSNumericSearch];
}

int main (int argc, const char * argv[]) 
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
	
	NSArray *unsorted = [NSArray arrayWithObjects: 
		@"1.0.0b11", @"1.0.0b4", @"1.0.0a3", nil ];

	NSArray* sorted = [unsorted sortedArrayUsingFunction:versionCompare context:nil];

	NSLog( @"unsorted: %@", unsorted );
	NSLog( @"sorted: %@", sorted );

    [pool drain];
    return 0;
}
Example output:
Code:
2010-04-21 09:51:26.600 a.out[4724] unsorted: ("1.0.0b11", "1.0.0b4", "1.0.0a3")
2010-04-21 09:51:26.600 a.out[4724] sorted: ("1.0.0a3", "1.0.0b4", "1.0.0b11")
 
A usual task is to compare two strings alphabetically or numerically. It is not usual to compare them using an arbitrary combination of the two.

iTunes sorts

Brandenburg Concerto No. 2 in F major, BWV 1047 - 2. Andante

exactly in the right place where I would expect it. Any combination of text and numbers.
 
i.yalovecky,

When I have trouble, I hack some code together. Here is that hack with chown33's array sort added in. Hopefully it will be helpful.


Code:
#import <Foundation/Foundation.h>

NSComparisonResult versionCompare( id str1, id str2, void *context )
{
	return [str1 compare:str2 options:NSNumericSearch];
}


int main (int argc, const char * argv[]) {
    CFShow(CFSTR("Comparing strings with numbers in them.\n"));
	
	NSObject* pool = [[NSAutoreleasePool alloc] init];
	
	static NSStringCompareOptions comparisonOptions =  NSNumericSearch;	
	
	NSString* lowStr; 
	lowStr = [NSString stringWithString:@"1.0.0a3"];
	NSString* midStr;
	midStr = [NSString stringWithString:@"1.0.0b4"];
	NSString* highStr;
	highStr = [NSString stringWithString:@"1.0.0b11"];

	NSInteger ordering;
	
	ordering = [lowStr compare: midStr options:comparisonOptions];
	NSLog(@"ordering of compare return value: %d", ordering);
	if ( ordering == NSOrderedAscending)
	{
		NSLog(@"Expected NSOrderedAscending: %@ < %@", lowStr, midStr);
	}
	else if ( ordering == NSOrderedDescending)
	{
		NSLog(@"NSOrderedDescending: %@ > %@", lowStr, midStr);
	}
	else
	{
		NSLog(@"NSOrderedSame: %@ = %@", lowStr, midStr);
	}
	
	
	ordering = [highStr compare: midStr options: NSNumericSearch];
	NSLog(@"ordering of compare return value: %d", ordering);
	if ( ordering == NSOrderedAscending)
	{
		NSLog(@"NSOrderedAscending: %@ < %@", highStr, midStr);
	}
	else if ( ordering == NSOrderedDescending)
	{
		NSLog(@"Expected NSOrderedDescending: %@ > %@", highStr, midStr);
	}
	else
	{
		NSLog(@"NSOrderedSame: %@ = %@", highStr, midStr);
	}


	NSArray *unsorted = [NSArray arrayWithObjects: midStr, highStr, lowStr, nil ];
	NSArray* sorted = [unsorted sortedArrayUsingFunction:versionCompare context:nil];
	NSLog( @"unsorted: %@", unsorted );
	NSLog( @"sorted: %@", sorted );


	[pool release];
	return 0;
}
 
Code:
	static NSStringCompareOptions comparisonOptions =  NSNumericSearch;

Your code has the potential problem that you store the ordering in a static variable, which is an initialisation that is only performed once when the program starts. If that static variable is changed later, the initialisation will not be done again. Big red flag going up. That's the kind of code where you may _think_ you are using NSNumericSearch, but you aren't. Example:

Code:
void test (void) {
  static int i = 5; 
  printf ("i should be five, it is %d\n", i);
  i = 6;
  printf ("i should be six, it is %d\n", i);
}

When you call test () the first time, it will print 5 and 6. On the second call, it will print 6 and 6.
 
I'm confused. That is the options flag, not the ordering result variable. I agree that if I want to change it later, it shouldn't be static.

Oh, static still allows the variable to be altered.

EDIT: Did some more research. Static limits scope within declared file so does allow changes. I should have used const.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.