0

Possible Duplicate:
Comparing version numbers
How to use compare on a version number where theres less parts in one number in Objective-C?

I am attempting to sort an NSMutableArray of custom objects based on a property called referenceID which essentially resembles a version number.

It seems that treating referenceID as an NSNumber and sorting it using compareTo: almost gets it right, but where it breaks is cases such as:

Result:           Should Be:
1.1.1             1.1.1
1.1.10            1.1.2
1.1.2             ...
...               1.1.9
1.1.9             1.1.10

(Where ... is 1.1.2 through 1.1.9)

Are there any built in functions that will sort this properly? Or should I get started writing the sorting algorithm?

Community
  • 1
  • 1
kz3
  • 785
  • 2
  • 10
  • 23
  • 1
    Also checkout [How to use compare on a version number where theres less parts in one number in Objective-C?](http://stackoverflow.com/questions/12308659/how-to-use-compare-on-a-version-number-where-theres-less-parts-in-one-number-in) – Black Frog Nov 29 '12 at 22:33
  • Ah, thank you. My Overflow-searching skills need some work... – kz3 Nov 29 '12 at 22:39

2 Answers2

2

If your reference id is a string, you can use localizedStandardCompare:, which compares numbers in strings according to their numerical value.

Example (with sortedArrayUsingComparator, because that is used by the OP in his comment):

NSArray *versions = @[@"2.1.1.1", @"2.10.1", @"2.2.1"];
NSArray *sorted = [versions sortedArrayUsingComparator:^NSComparisonResult(NSString *s1, NSString *s2) {
    return [s1 localizedStandardCompare:s2];
}];
NSLog(@"%@", sorted);

Output:

2012-11-29 23:51:28.962 test27[1962:303] (
    "2.1.1.1",
    "2.2.1",
    "2.10.1"
)
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • he has version numbers though.. dot separated versions of different length. does the function do that? – Daij-Djan Nov 29 '12 at 22:30
  • @Daij-Djan: Yes, that works with numbers of different length. – Martin R Nov 29 '12 at 22:33
  • Perhaps I'm doing something wrong here, but I'm still getting the same results as above with this: [standards sortedArrayUsingComparator:^NSComparisonResult(Standard *s1, Standard *s2) { return [[NSString stringWithFormat:@"%@", s1.referenceID] localizedStandardCompare:[NSString stringWithFormat:@"%@", s2.referenceID]]; – kz3 Nov 29 '12 at 22:36
  • @Martin R : Cool didnt know that one :) Thanks useful – Daij-Djan Nov 29 '12 at 22:36
  • @KyleBanks: I have added example code using `sortedArrayUsingComparator`, does that help? – Martin R Nov 29 '12 at 22:43
  • why not sortedArrayUsingSelector:@selector(localizedStandardCompare:)];? is that somehow bad.. its shorter... (honest sub-question of mine) – Daij-Djan Nov 29 '12 at 22:45
  • @Daij-Djan: Because the OP's array does not contain strings, but `Standard` objects which have a `referenceID` property, see his above comment. – Martin R Nov 29 '12 at 22:47
  • Sample output using this code: 2.1.1.1, 2.10.1, 2.2.1. It does however work properly on the final point of the version number. – kz3 Nov 29 '12 at 22:50
  • @KyleBanks: That is strange ... I have used your data in my test program, and it produces the expected result. See my updated answer, it is copy/paste from my actual output. – Martin R Nov 29 '12 at 22:53
  • This is very strange, I just copied your above code directly into my project, and I get the same result. However sorting based off the `Standard` referenceID, the results are off. I've accepted your answer because clearly this does work, but something is wrong with my own code that I will need to debug. Thanks! – kz3 Nov 29 '12 at 22:58
  • @KyleBanks: You are welcome. - Perhaps the conversion from reference id to string does not give the expected result? (Just an idea.) – Martin R Nov 29 '12 at 23:00
  • @MartinR I wish it was that simple, but alas that was my first thought as well. I'll keep digging. – kz3 Nov 29 '12 at 23:03
  • I don't think this is reliable. From Apple's documentation: "The exact sorting behavior of this method is different under different locales and may be changed in future releases." See https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html#//apple_ref/occ/instm/NSString/localizedStandardCompare: – Andrew Rondeau Feb 04 '14 at 20:18
0

sort it with a block


@autoreleasepool {
    //in this example, array of NSStrings
    id array = @[@"1.1.1",@"2.2",@"1.0",@"1.1.0.1",@"1.1.2.0", @"1.0.3", @"2.1.1.1", @"2.1.1", @"2.1.10"];

    //block
    id sorted = [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        NSArray *comps1 = [obj1 componentsSeparatedByString:@"."];
        NSArray *comps2 = [obj2 componentsSeparatedByString:@"."];

        //get ints from comps
        int res1 = 0;
        for (int i=0; i<comps1.count; i++) {
            res1 += [comps1[i] intValue] * (4 - i);
        }
        int res2 = 0;
        for (int i=0; i<comps2.count; i++) {
            res2 += [comps2[i] intValue] * (4 - i);
        }

        return res1<res2 ? NSOrderedAscending : res1>res2 ? NSOrderedSame : NSOrderedDescending;
    }];

    NSLog(@"%@", sorted);
}
Daij-Djan
  • 49,552
  • 17
  • 113
  • 135