简体   繁体   中英

Is it possible to change priority(weight) of certain symbols in sorting?

I want to create a comparator for string values, but according to https://www.cs.cmu.edu/~pattis/15-1XX/common/handouts/ascii.html underscore symbol has bigger value than any digit. Is it possible to change it somehow?

Short answer

Yes, it is. You need a custom string comparator.

Solution

Let's say you need to sort a list of strings:

[a_123, ab123, a123, 123, _123]

If you sort it using Collections.sort then it'll be sorter in the following order:

[123, _123, a123, a_123, ab123]

But you want to override the "weight" of _ . To achieve this you need a custom string comparator. Let's copy and modify a bit java.lang.String#compareTo :

private int customStringComparator(String s1, String s2) {
    int len1 = s1.length();
    int len2 = s2.length();
    int lim = Math.min(len1, len2);
    char v1[] = s1.toCharArray();
    char v2[] = s2.toCharArray();

    int k = 0;
    while (k < lim) {
        char c1 = v1[k];
        char c2 = v2[k];
        // You can add your custom comparison here:
        if ('_' == c1 && Character.isDigit(c2)) {
            // We intentionally return inverted result
            return c2  - c1;
        }else if(c1 != c2) {
            return c1 - c2;
        }
        k++;
    }
    return len1 - len2;
}

Now we can pass our customStringComparator to Collections.sort :

Collections.sort(list, this::customStringComparator);

The list will be sorted in the following order:

[_123, 123, a_123, a123, ab123]

As you can see, now the _ precedes digits.

This might work:

private int compareStrings(String o1, String o2) {
    if(o1.matches("\\d+") && o2.equals("_")) {
        return 1;
    }
    if(o1.equals("_") && o2.matches("\\d+")) {
        return -1;
    }
    return o1.compareTo(o2);
}

And then define your comparator like so:

Comparator<String> stringComparator2 = this::compareStrings;

EDIT:

According to not working for string with _ in the middle, how about just replacing _ with character that is before in ASCII table just for comparing (like " " for example):

public static int compareStrings(String o1, String o2) {
    o1 = o1.replaceAll("_", " ");
    o2 = o2.replaceAll("_", " ");
    return o1.compareTo(o2);
}

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