如何在java中对包含数字的字符串进行排序?
示例:abc12,abc2,xyz3,pqr23,pqr99,wer12
需要获得abc2,abc12,pqr23,pqr99,wer12
我尝试使用比较器,但只能比较需要比较字符串和数字的数字。
请帮我。
感谢
答案 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
的方式输出它们,因为这样可以帮助您轻松排序。
您是否可以解析并更新字符串,从abc2
到abc02
如果你这样做,那之后的排序就可以了。不是吗?
所以,只要有一个数字填充它之前只有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);
}
}
}