Sorting an NSMutableArray of strings by string val

2020-04-13 20:04发布

问题:

I get an array of strings with the following strings, there is a certain patern to the strings

str1 str51 str3 str4 str10 str39 str31 str191

Every string starts with 'str' and has a number appended onto the end of it.

Is there a neath way to sort the array so it lists the strings in order of value

str1 str3 str4 str10 str31 str39 str51 str191

I can see a way to do it by writing some recursive function that will

NSString * firstString = [[strArray objectAtIndex:i].substringFromIndex:3];
NSString * secondString = [[strArray objectAtIndex:i+1].substringFromIndex:3];

if ([firstString intValue] < [secondString intValue])
{
    //do nothing they order is correct
}
else
{
    //swap the order of the 2 strings in the array
}

But thats very rudimentary code, Is there some mechanism in Objective-C or a nice code trick to handle this sorting better?

Many Thanks, -Code

回答1:

If they all start with the same prefix, I believe that the default sort will handle them appropriately. By this, I mean:

[someArray sortUsingSelector:@selector(compare:)];

If, for some reason, this isn't working, then you can use a block. Try this:

NSArray *sortedArray = [someArray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) 
{
    //Default compare, to protect against cast
    if (![a isKindOfClass:[NSString class]] || ![b isKindOfClass:[NSString class]]) {
        return ([a compare:b]);
    }
    else {
        NSString *aString = (NSString*) a;
        NSString *bString = (NSString*) b;
        int aInt = [[a.substringFromIndex:3] intValue];
        int bInt = [[b.substringFromIndex:3] intValue];
        return [aInt < bInt];
    }
}];


回答2:

You could sort it like this

NSArray *sortedArray = [unsortedArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    NSString * str1 = [(NSString *)obj1 substringFromIndex:3];
    NSString * str2 = [(NSString *)obj2 substringFromIndex:3];
    return [str1 compare:str2 options:NSNumericSearch];
}];


回答3:

You can define a comparator function with whatever behavior you want. The one below will emulate the behavior of Finder in Mac OS, ignoring case and respecting numbers occurring at the end of strings. The order will be dependent on the provided locale, though, so if you want the results to be absolutely consistent, you should pick a locale and hard-code it.

int finderSortWithLocale(id string1, id string2, void *locale)
{
    static NSStringCompareOptions comparisonOptions =
        NSCaseInsensitiveSearch | NSNumericSearch |
        NSWidthInsensitiveSearch | NSForcedOrderingSearch;

    NSRange string1Range = NSMakeRange(0, [string1 length]);

    return [string1 compare:string2
                    options:comparisonOptions
                    range:string1Range
                    locale:(__bridge NSLocale *)locale];
}

You should definitely read the documentation on each of those options to ensure it does what you're looking for.

To use such a comparator to efficiently sort a string array, use the sortedArrayUsingFunction:context: method:

NSArray *sortedArray = [stringsArray sortedArrayUsingFunction:finderSortWithLocale context:(__bridge void *)[NSLocale currentLocale]];


回答4:

Create a NSSortDescriptor and sort the array on the key: "description". Like This:

NSMutableArray *array = [NSMutableArray arrayWithCapacity:0]; //Your Array of NSStrings
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES];
array = [array sortedArrayUsingDescriptors:@[descriptor]];


回答5:

NSSortDescriptor *sortByName = [NSSortDescriptor sortDescriptorWithKey:@"datetime"
                                                             ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortByName];
NSArray *sortedArray = [myArrayNonsort sortedArrayUsingDescriptors:sortDescriptors];


回答6:

sortedArray = [anArray sortedArrayUsingSelector: @selector(localizedCaseInsensitiveCompare:)];

input:anArray output:sortedArray

refer the docs