如何排序字符串包含java中的数字

时间:2014-01-17 10:29:53

标签: java sorting

如何在java中对包含数字的字符串进行排序? 示例:abc12,abc2,xyz3,pqr23,pqr99,wer12需要获得abc2,abc12,pqr23,pqr99,wer12我尝试使用比较器,但只能比较需要比较字符串和数字的数字。 请帮我。 感谢

3 个答案:

答案 0 :(得分:2)

如果您始终使用格式(lettersNumbers),则可以使用此正则表达式(取自here并稍加修改):

private static final String PATTERN = "[^a-z0-9]+|(?<=[a-z])(?=[0-9])|(?<=[0-9])(?=[a-z])";
    public static void main(String[] args) {
        List<String> l = Arrays.asList("abc12","abc2","xyz3","pqr23","pqr99","wer12");
        Collections.sort(l, new Comparator<String>(){
            @Override
            public int compare(String arg0, String arg1) {
                String [] arr0 = arg0.split(PATTERN);
                String [] arr1 = arg1.split(PATTERN);
                int cmp = arr0[0].compareTo(arr1[0]);
                return cmp != 0 ? cmp : Integer.compare(Integer.parseInt(arr0[1]), Integer.parseInt(arr1[1]));
            }           
        });
        System.out.println(l);
    }

输出:

[abc2, abc12, pqr23, pqr99, wer12, xyz3]

答案 1 :(得分:1)

修改

以简单方式执行此操作的一种方法是使用前面的零填充数字。 所以,如果你有像

这样的字符串
abc1
abc10 
abc100

您解析字符串并填充数字占据相同空间的字符串。 所以你的字符串会变成

abc001
abc010
abc100

现在,只需对它们进行排序,自然排序应该可以毫不费力地对它们进行排序。

如果你知道有多少数字将构成字符串的一部分,那么这就是全部。

此外,您可能希望以abc001而不是abc1的方式输出它们,因为这样可以帮助您轻松排序。

您是否可以解析并更新字符串,从abc2abc02 如果你这样做,那之后的排序就可以了。不是吗?

所以,只要有一个数字填充它之前只有0.

但是,尽管如此,在我看来它仍然比我的比较器更容易解决问题

答案 2 :(得分:1)

使用自然分类:

package org.cougaar.util;

import java.util.Comparator;

/**
 * A sorting comparator to sort strings numerically,
 * ie [1, 2, 10], as opposed to [1, 10, 2].
 */
public final class NaturalOrderComparator<T> implements  Comparator<T> {

    public static final Comparator<String> NUMERICAL_ORDER = new NaturalOrderComparator<String>(false);
    public static final Comparator<String> CASEINSENSITIVE_NUMERICAL_ORDER = new NaturalOrderComparator<String>(true);

    private final boolean caseInsensitive;

    private NaturalOrderComparator(boolean caseInsensitive) {
        this.caseInsensitive = caseInsensitive;
    }

    int compareRight(String a, String b) {
        int bias = 0;
        int ia = 0;
        int 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;
            } else if (!Character.isDigit(ca)) {
                return -1;
            } else if (!Character.isDigit(cb)) {
                return +1;
            } else if (ca < cb) {
                if (bias == 0) {
                    bias = -1;
                }
            } else if (ca > cb) {
                if (bias == 0)
                    bias = +1;
            } else if (ca == 0 && cb == 0) {
                return bias;
            }
        }
    }

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

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

        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 zeros
            while (ca == '0') {
                if (ca == '0') {
                    nza++;
                } else {
                    // only count consecutive zeroes
                    nza = 0;
                }

                // if the next character isn't a digit, then we've had a run of only zeros
                // we still need to treat this as a 0 for comparison purposes
                if (!Character.isDigit(charAt(a, ia+1)))
                    break;

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

            while (cb == '0') {
                if (cb == '0') {
                    nzb++;
                } else {
                    // only count consecutive zeroes
                    nzb = 0;
                }

                // if the next character isn't a digit, then we've had a run of only zeros
                // we still need to treat this as a 0 for comparison purposes
                if (!Character.isDigit(charAt(b, ib+1)))
                    break;

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

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

            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;
            } else if (ca > cb) {
                return +1;
            }

            ++ia;
            ++ib;
        }
    }

    private char charAt(String s, int i) {
        if (i >= s.length()) {
            return 0;
        } else {
            return caseInsensitive ? Character.toUpperCase(s.charAt(i)) : s.charAt(i);
        }
    }


}