简体   繁体   中英

Sort strings that contains number

I have list of strings that contains numbers:

Example:

String 1.0.2
String 2.1.2
String 10.0.1
String 3.0.1
String 2.3.1
String 10.2.1

I need to sort this list and get this:

String 1.0.2
String 2.1.2
String 2.3.1
String 3.0.1
String 10.0.1
String 10.2.1

But if i use java functions Collections.sort i get this:

String 1.0.2
String 10.0.1
String 10.2.1
String 2.1.2
String 2.3.1
String 3.0.1

Edit:

I've tried with this comparator:

public int compare(String o1, String o2) {
    int a = Integer.parseInt(o1.split(" ")[1].replace(".", ""));
    int b = Integer.parseInt(o2.split(" ")[1].replace(".", ""));

    return a-b;
}

When i run app i get this error java.lang.NumberFormatException: For input string: "Unknown" how can i check is there strings that doesn't contains number so that i can test this comparator?

you can get the numeric value of those strings and use java8 streams

List<String> myList = Arrays.asList("String 1.0.2", "String 2.1.2", "String 10.0.1", "String 3.0.1",
            "String 2.3.1", "String 10.2.1");

myList.sort((x, y) -> Integer.compare(Integer.parseInt(x.replace(".", "").split(" ")[1]),
            Integer.parseInt(y.replace(".", "").split(" ")[1])));
System.out.println(myList);

Instead you can use a Comparator like this :

List<String> list = Arrays.asList("1.0.2", "2.1.2", "10.0.1", "3.0.1", "2.3.1", "10.2.1");
System.out.println(list);
Collections.sort(list, (o1, o2) -> {
    return Integer.parseInt(o1.replace(".", "")) - Integer.parseInt(o2.replace(".", ""));
});
System.out.println(list);

Outputs

[1.0.2, 2.1.2, 10.0.1, 3.0.1, 2.3.1, 10.2.1]
[1.0.2, 2.1.2, 2.3.1, 3.0.1, 10.0.1, 10.2.1]

The idea is :

  1. replace all . with empty
  2. convert your number to the correct number
  3. compare the result like any number.

you can write a comparator like:

@Override
public int compare(String o1, String o2) {
    int a = Integer.parseInt(o1.split(" ")[1].replace(".", ""));
    int b = Integer.parseInt(o2.split(" ")[1].replace(".", ""));
    return a - b;
}

And then just:

CustomComparator comp = new CustomComparator();
Collections.sort(list, comp);

Hope it Helps!

You need to tokenize them, and following compare from the most significant token to the end. as an example You can do as follow to compare two sequence a and b.

    public int compare(Sring a,String b){
        String[] aToken = a.slpit(".");
        String[] bToken = b.slpit(".");
        if (aToken.length > bToken.length){
            return 1;
         }
        if (bToken.length > aToken.length){
            return -1;
        }
        for (int i=0; i<bToken.length; i++){
            if (aToken[i].compareTo(b[i]Token) != 0){
               return aToken[i].compareTo(bToken[i]);
           }
       }
      return 0;
    }

from this snippet you can build your comparator hope this help

I've solved my problem wirth this comparator:

public int compare(String o1, String o2)
        {
            String a = o1.toString();
            String b = o2.toString();

            int ia = 0, ib = 0;
            int nza = 0, nzb = 0;
            char ca, cb;

            while (true) {
                // Only count the number of zeroes leading the last number compared
                nza = nzb = 0;

                ca = charAt(a, ia);
                cb = charAt(b, ib);

                // skip over leading spaces or zeros
                while (Character.isSpaceChar(ca) || ca == '0') {
                    if (ca == '0') {
                        nza++;
                    } else {
                        // Only count consecutive zeroes
                        nza = 0;
                    }

                    ca = charAt(a, ++ia);
                }

                while (Character.isSpaceChar(cb) || cb == '0') {
                    if (cb == '0') {
                        nzb++;
                    } else {
                        // Only count consecutive zeroes
                        nzb = 0;
                    }

                    cb = charAt(b, ++ib);
                }

                // Process run of digits
                if (Character.isDigit(ca) && Character.isDigit(cb)) {
                    int bias = compareRight(a.substring(ia), b.substring(ib));
                    if (bias != 0) {
                        return bias;
                    }
                }

                if (ca == 0 && cb == 0) {
                    // The strings compare the same. Perhaps the caller
                    // will want to call strcmp to break the tie.
                    return nza - nzb;
                }
                if (ca < cb) {
                    return -1;
                }
                if (ca > cb) {
                    return +1;
                }

                ++ia;
                ++ib;
            }
        }

        int compareRight(String a, String b)
        {
            int bias = 0, ia = 0, ib = 0;

            // The longest run of digits wins. That aside, the greatest
            // value wins, but we can't know that it will until we've scanned
            // both numbers to know that they have the same magnitude, so we
            // remember it in BIAS.
            for (;; ia++, ib++)
            {
                char ca = charAt(a, ia);
                char cb = charAt(b, ib);

                if (!Character.isDigit(ca) && !Character.isDigit(cb)) {
                    return bias;
                }
                if (!Character.isDigit(ca)) {
                    return -1;
                }
                if (!Character.isDigit(cb)) {
                    return +1;
                }
                if (ca == 0 && cb == 0) {
                    return bias;
                }

                if (bias == 0) {
                    if (ca < cb) {
                        bias = -1;
                    } else if (ca > cb) {
                        bias = +1;
                    }
                }
            }
        }

        static char charAt(String s, int i) {
            return i >= s.length() ? 0 : s.charAt(i);
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM