簡體   English   中英

如何對字母數字字符串進行排序

[英]How to sort Alphanumeric String

我對包含整數的字符串進行排序有問題。 如果我使用下面的代碼,我會得到這樣的排序:1some, 2some, 20some, 21some, 3some, some

但是我希望它排序為:1some,2some,3some,20some,21some,some

我怎樣才能做到這一點?

謝謝!

Collections.sort(selectedNodes,
    new Comparator<DefaultMutableTreeNode>() {
    @Override
    public int compare(DefaultMutableTreeNode o1,
        DefaultMutableTreeNode o2) {
        return o1.getUserObject().toString()
            .compareTo(o2.getUserObject().toString());
    }
    });

這是一個關於如何執行此操作的獨立示例(未特別優化):

final Pattern p = Pattern.compile("^\\d+");
String[] examples = { 
   "1some", "2some", "20some", "21some", "3some", "some", "1abc", "abc"
};
Comparator<String> c = new Comparator<String>() {
    @Override
    public int compare(String object1, String object2) {
        Matcher m = p.matcher(object1);
        Integer number1 = null;
        if (!m.find()) {
            return object1.compareTo(object2);
        }
        else {
            Integer number2 = null;
            number1 = Integer.parseInt(m.group());
            m = p.matcher(object2);
            if (!m.find()) {
                return object1.compareTo(object2);
            }
            else {
                number2 = Integer.parseInt(m.group());
                int comparison = number1.compareTo(number2);
                if (comparison != 0) {
                    return comparison;
                }
                else {
                    return object1.compareTo(object2);
                }
            }
        }
    }
};
List<String> examplesList = new ArrayList<String>(Arrays.asList(examples));
Collections.sort(examplesList, c);
System.out.println(examplesList);

輸出

[1abc, 1some, 2some, 3some, 20some, 21some, abc, some]

解釋

  • 該示例使用常量Pattern來推斷數字是否在String的起始位置。
  • 如果第一個String不存在,它將按原樣與第二個進行比較。
  • 如果確實存在於第一個中,它會檢查第二個。
  • 如果第二個中不存在,則再次按原樣比較兩個String s
  • 如果兩者都存在,則比較Integer s而不是整個String s,因此導致數字比較而不是字典比較
  • 如果數字比較相同,則返回到整個String的字典比較(感謝MihaiC發現這個)

您的解決方案在於Alphanum 算法,您可以像這樣實現

首先制作一個字母數字比較器,將字符串分成字符串或整數部分。

public class AlphaNumericalComparator implements Comparator<String> {
    @Override
    public int compare(String o1, String o2) {
        List<Object> parts1 = partsOf(o1);
        List<Object> parts2 = partsOf(o2);
        while (!parts1.isEmpty() && !parts2.isEmpty()) {
            Object part1 = parts1.remove(0);
            Object part2 = parts2.remove(0);
            int cmp = 0;
            if (part1 instanceof Integer && part2 instanceof Integer) {
                cmp = Integer.compare((Integer)part1, (Integer)part2);
            } else if (part1 instanceof String && part2 instanceof String) {
                cmp = ((String) part1).compareTo((String) part2);
            } else {
                cmp = part1 instanceof String ? 1 : -1; // XXXa > XXX1
            }
            if (cmp != 0) {
                return cmp;
            }
        }
        if (parts1.isEmpty() && parts2.isEmpty()) {
            return 0;
        }
        return parts1.isEmpty() ? -1 : 1;
    }

    private List<Object> partsOf(String s) {
        List<Object> parts = new LinkedList<>();
        int pos0 = 0;
        int pos = 0;
        boolean wasDigit = false;
        while (true) {
            if (pos >= s.length()
                    || Character.isDigit(s.charAt(pos)) != wasDigit) {
                if (pos > pos0) {
                    String part = s.substring(pos0, pos);
                    parts.add(wasDigit? Integer.valueOf(part) : part);
                    pos0 = pos;
                }
                if (pos >= s.length()) {
                    break;
                }
                wasDigit = !wasDigit;
            }
            ++pos;
        }
        return parts;
    }
};

然后在你自己的比較器中使用這個比較器,在 Java 8 中你可以簡單地使用 Comparator 的靜態方法。

您需要實現自己的Comparator來進行這種自定義排序。 默認的String.compareTo()方法似乎在字符之前對數字進行排序。 20some 020some中的s進行3some0具有更高的排序優先級,因此整個單詞首先被排序。
您需要做的是:嘗試將字符串拆分為數字和字符部分。 這是一項艱巨的任務,因為這些String可以包含許多這些部分(或者不是?)。 您可以使用像Alphanum這樣的算法,Murtaza 已經向您展示過。
如果你想自己實現它,你可以檢查,數字部分在哪里結束。 然后使用Integer.parse()將其解析為int 如果兩個String中都存在int部分,則比較它們,然后比較其余部分。 好吧,這可能不是最專業的解決方案,但作為初學者,您可能希望自己制作這些東西來學習它。

您不能使用默認的 String compareTo() 而是需要按照以下算法比較字符串。

  1. 逐個字符循環遍歷第一個和第二個 String 並獲取所有字符串或數字的塊
  2. 檢查塊是數字還是字符串
  3. 如果數字按數字排序,否則使用 String compareTo()

重復這些步驟。

您可以使用正則表達式在一行中完成它的核心以提取數字部分:

Collections.sort(selectedNodes, new Comparator<DefaultMutableTreeNode>() {
    @Override
    public int compare(DefaultMutableTreeNode o1,
        DefaultMutableTreeNode o2) {
        return Integer.parseInt(o1.getUserObject().toString().replaceAll("\\D", "")) -
            Integer.parseInt(o2.getUserObject().toString().replaceAll("\\D", ""));
    }
});

這是一個有效的解決方案是 Java。 如果您對代碼有任何建議,請在我的Gist上告訴我。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class FB {

    public static int comparator(String s1, String s2) {

        String[] pt1 = s1.split("((?<=[a-z])(?=[0-9]))|((?<=[0-9])(?=[a-z]))"); 
        String[] pt2 = s2.split("((?<=[a-z])(?=[0-9]))|((?<=[0-9])(?=[a-z]))"); 
//pt1 and pt2 arrays will have the string split in alphabets and numbers

        int i=0;
        if(Arrays.equals(pt1, pt2))
            return 0;
        else{
            for(i=0;i<Math.min(pt1.length, pt2.length);i++)
                if(!pt1[i].equals(pt2[i])) {
                    if(!isNumber(pt1[i],pt2[i])) {
                        if(pt1[i].compareTo(pt2[i])>0)
                            return 1;
                        else
                            return -1;
                    }
                    else {
                        int nu1 = Integer.parseInt(pt1[i]);
                        int nu2 = Integer.parseInt(pt2[i]);
                        if(nu1>nu2)
                            return 1;
                        else
                            return -1;
                    }
                }
        }

        if(pt1.length>i)
            return 1;
        else
            return -1;
    }

    private static Boolean isNumber(String n1, String n2) {
        // TODO Auto-generated method stub
        try {
            int nu1 = Integer.parseInt(n1);
            int nu2 = Integer.parseInt(n2);
            return true;
        }
        catch(Exception x) {
            return false;
        }

    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        String[] examples = {"1some", "2some", "20some", "21some", "3some", "some", "1abc", "abc"};
        List<String> values = new ArrayList<String>(Arrays.asList(examples));

        System.out.println(values);
        Comparator<String> com = (o1,o2) -> {return comparator(o1,o2);}; //lambda expression

        Collections.sort(values,com);
        System.out.println(values);
    }
}

輸出:

[1some, 2some, 20some, 21some, 3some, some, 1abc, abc]
[1abc, 1some, 2some, 3some, 20some, 21some, abc, some]

如果您知道該模式始終是 NUMALPHA 或 ALPHANUM 並且 alpha 始終相同:

if(str1.length() != str2.length()){
   return str1.length() - str2.length();
}

return str1.compareTo(str2);

如果您有字母數字字符串數組,則可以直接使用

Arrays.sort(Array_name)

然后打印:

for(String a : Array_name)
    System.out.print(a);

如何使用比較器在 Java 中對字符串、字母數字和數字值進行排序

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class AlphaNumericSorting {
    public static void main(String[] args) {
        final Pattern p = Pattern.compile("^\\d+");
        String[] examples = { "CD", "DE", "0A", "0B", "0C", "12", "0K", "TA", "0D", "01", "02", "11", "AB", "MN" };
        Comparator<String> c = new Comparator<String>() {
            @Override
            public int compare(String object1, String object2) {
                Matcher m = p.matcher(object1);
                Integer number1 = null;
                if (!m.find()) {
                    Matcher m1 = p.matcher(object2);
                    if (m1.find()) {
                        return object2.compareTo(object1);
                    } else {
                        return object1.compareTo(object2);
                    }
                } else {
                    Integer number2 = null;
                    number1 = Integer.parseInt(m.group());
                    m = p.matcher(object2);
                    if (!m.find()) {
                        // return object1.compareTo(object2);
                        Matcher m1 = p.matcher(object1);
                        if (m1.find()) {
                            return object2.compareTo(object1);
                        } else {
                            return object1.compareTo(object2);
                        }
                    } else {
                        number2 = Integer.parseInt(m.group());
                        int comparison = number1.compareTo(number2);
                        if (comparison != 0) {
                            return comparison;
                        } else {
                            return object1.compareTo(object2);
                        }
                    }
                }
            }
        };
        List<String> examplesList = new ArrayList<String>(Arrays.asList(examples));
        Collections.sort(examplesList, c);
        System.out.println(examplesList);
    }
}

輸出:-

[AB, CD, DE, MN, TA, 0A, 0B, 0C, 0D, 0K, 01, 02, 11, 12 ]

    String [] str = new String[]{"1some", "2some", "20some", "21some", "3some", "some"};
    List<String> list = Arrays.asList(str);

    Collections.sort(list, String.CASE_INSENSITIVE_ORDER);
    System.out.println(list);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM