1

I'm trying to sort the list of strings which has versions but fail to do this:

List<String> src = new List<String>{'7.1.2', '8.1.3', '11.0.5', '5.x', '10.0.89', '12.13.14'};

List<String> res = new List<String>();
for(Integer i = src.size()-1; i>=0; i--) {
    res.add(src.get(i));
}

System.Debug(res);

The Apex Developer Console returns the following result:

USER_DEBUG [30]|DEBUG|(12.13.14, 10.0.89, 5.x, 11.0.5, 8.1.3, 7.1.2)

How to fix this?

3

This is a general approach I'd suggest you consider taking considering the nature of your data.

If you don't want to use comparable, you will need to sort based on the "major" version, followed by the "minor" (for each major version), then each "finest" version (for the minor version). That will allow you to deal with the ones that don't have finer levels or those that don't use numbers like your 5.x

Use the '.' as separators to know what portions of your string to use to sort on for each level. You may want to save the results to a map by level (or something along those lines) where you can pull the results from each out and not have deeply nested loops in your code. I would use a RegEx pattern to assist with the coding.

EDIT

In response to comments...

Note: I have not tested the code below, but it does appear that it will compile.

List<String> src = new List<String>{
            '7.1.2', '8.1.3', '11.0.5', '5.x', '10.0.89', '12.13.14'};

// declare maps and lists you will need
map<string, string>srcOrderMap = new map<string, string>();
map<string, list<string>>srcOrderLstMap = new map<string, List<string>>();

Integer count = 0;
integer iString = string.valueOf(count);
integer iString=string.valueOf(count);
list<string>b_count = new list<string>();
// create map for where you started from for complete string and list string
for(string s:src){
    b_count=b.split('.');
    srcOrderMap.put(iString,b_count);
    srcOrderMap.put(iString,s);
    count++;
}

// declare variables for next loop
map<string, string>srcCol0OrderMap = new map<string, string>();
map<string, string>srcCol1OrderMap = new map<string, string>();
map<string, string>srcCol2OrderMap = new map<string, string>();
list<string>sArrayCol0 = new list<string>();
list<string>sArrayCol1 = new list<string>();
list<string>sArrayCol2 = new list<string>();

// create maps for each column and lists of those values
for(integer s=0;s=srcOrderMap.size();s++){
    for(integer c=0;c<3;c++){

        if(c == 0){
            sArrayCol0.add.srcOrderMap.get(string.valueOf(s)[0]);
        }
        if(c == 1){
            sArrayCol1.add.srcOrderMap.get(string.valueOf(s)[1]);
        }
        if(c == 2){
            sArrayCol2.add.srcOrderMap.get(string.valueOf(s)[2]);
        }
        srcCol0OrderMap.put(string.valueOf(s), sArrayCol0[string.valueOf(s)]);
        srcCol1OrderMap.put(string.valueOf(s), sArrayCol1[string.valueOf(s)]);
        srcCol2OrderMap.put(string.valueOf(s), sArrayCol2[string.valueOf(s)]);
    }

}

Now you can do a sort on column 0, after which you can do a sub-sort on column1 where any values in column 0 are the same to determine which value gets moved up or down in your map.

// sort the values in column 0
sArrayCol0.sort();

I'll leave it to you to determine how you want to find the duplicate values in the list. There are lots of solutions to that problem you should be able to find on your own.

Once you have the sorted column 0 results, all you need to do is go back to your original source map and retrieve the original values that are also ready for you in sArrayCol1 where they're ready for you to sort() and compare. The results of that sort will determine which one of the values in Col 0 "wins". If both are equal, then you sort again on based on the values found in sArrayCol2 as once again are referenced in the original source map.

That's the reason I recommended using maps, so you can keep track of these values and will always be able to go back and reference them from where you began as you re-order your records at different levels. I hope this provides you with the "map" you need to reach your destination.

  • I see. I was able to get three lists with major, minor and patch numbers (I get rid of versions like 5.x), e.g.: major = (7, 8, 11, 10, 12) minor = (1, 1, 0, 0, 13) patch = (2, 3, 5, 89, 14) But, actually, I'm not sure how to sort them now from these three lists. Could you please suggest? – heisenberg Aug 6 '18 at 19:53
  • @heisenberg See my edited answer – crmprogdev Aug 8 '18 at 18:08
6

Apex has a Version class that supports major.minor and major.minor.patch numbering. If you work with those objects:

List<Version> src = new List<Version>{
    new Version(7, 1, 2),
    new Version(8, 1, 3),
    ...
};

you get sorting for free (as compareTo is implemented) where this sorts in place:

src.sort();

and the string format for each Version is as expected e.g. "7.1.2".

Note that there is no support for your "5.x" though; if you need that you will have to create your own class as David discusses.

5

It's doing exactly what you asked it to do: it reversed the order of the list, which is what that for loop does.

If you want to sort the strings, you need to perform a sort operation by calling List.sort(). Since your list is of String instances and Apex does not support custom sort functions, that would return your strings sorted in the manner that the String class defines: lexicographic order, which may or may not be exactly what you want here.

If you need to define the semantics of how these version strings and their subcomponents are to be sorted (does .x come before or after .0, for example?), you'll need to define a custom Apex class that implements the Comparable interface to store each version string, possibly breaking it down into its components. You'd then implement logic in its compareTo() method to make List.sort() work the way you want on a List<MyVersionObject>.

Alternately, you could implement any one of the standard sorting algorithms (quicksort, etc.) by hand and apply it to this list of Strings.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.