英文:
Java - Sort a list of objects that includes a special character
问题
基本上,我有一个对象的ArrayList,如下所示:
[{name: 'A'}, {name: 'B'}, {name:'?'}]
我希望对它们进行排序,以使问号像上面一样排在末尾。
但使用以下代码:
Collections.sort(myList);
这总是导致带有问号的对象首先出现,我认为这是由于ASCII排序造成的?我认为正确的方法是使用比较器函数,但我不确定在字母和特殊字符方面该如何实现?
我应该如何实现这个?
英文:
Basically i have an arraylist of objects like so:
[{name: 'A'}, {name: 'B'}, {name:'?'}]
I want to sort these so that the question mark is at the end like above.
But using the below code.
Collections.sort(myList);
This always results in the object with the question mark first, I think this is due to ASCII ordering? I think the correct way forward is to use a comparator function but i'm not sure how that would take shape with letters and special characters?
How would I implement this?
答案1
得分: 2
一种替代方法是,可以使用基于规则的排序器将任何标点符号排序到末尾。
一个示例:
List<String> words = Arrays.asList(
"?dog", "rat", "456", "123", "dog", "pig", "?cat", "!rat", "cat"
);
String englishRules = ("< a,A < b,B < c,C < d,D < e,E < f,F "
+ "< g,G < h,H < i,I < j,J < k,K < l,L "
+ "< m,M < n,N < o,O < p,P < q,Q < r,R "
+ "< s,S < t,T < u,U < v,V < w,W < x,X "
+ "< y,Y < z,Z < 0,1,2,3,4,5,6,7,8,9");
RuleBasedCollator rbc = new RuleBasedCollator(englishRules);
rbc.setStrength(Collator.PRIMARY);
Collections.sort(words, rbc);
words.forEach((word) -> {
out.print(word + " ");
});
这将输出:
cat dog pig rat 123 456 !rat ?cat ?dog
需要注意的点:
-
这个特定的示例仅限于英文排序。
-
这种通用技术之所以有效,是因为所有未提及的字符都被排序到末尾。因此,不仅标点符号在英文字母和数字之后排序,其他字符/符号(例如其他脚本使用的字符)也是如此。
-
如果你想要非Unicode标点符号的排序顺序,它们需要在规则字符串中用单引号括起来:
"... < 0,1,2,3,4,5,6,7,8,9 < '?' < '!'"
英文:
An alternative approach - one which sorts any punctuation to the end - can be achieved using a rules-based collator.
An example:
List<String> words = Arrays.asList(
"?dog", "rat", "456", "123", "dog", "pig", "?cat", "!rat", "cat"
);
String englishRules = ("< a,A < b,B < c,C < d,D < e,E < f,F "
+ "< g,G < h,H < i,I < j,J < k,K < l,L "
+ "< m,M < n,N < o,O < p,P < q,Q < r,R "
+ "< s,S < t,T < u,U < v,V < w,W < x,X "
+ "< y,Y < z,Z < 0,1,2,3,4,5,6,7,8,9");
RuleBasedCollator rbc = new RuleBasedCollator(englishRules);
rbc.setStrength(Collator.PRIMARY);
Collections.sort(words, rbc);
words.forEach((word) -> {
out.print(word + " ");
});
This outputs:
cat dog pig rat 123 456 !rat ?cat ?dog
Points to note:
-
This specific example is limited to an English collation.
-
The general technique works because all non-mentioned characters are sorted to the end. So, not only are punctuation symbols sorted after English letters and digits - but so is every other character/symbol (e.g. those used by other scripts).
-
If you want a non-Unicode ordering of punctuation symbols, they need to be surrounded by single quotes in your rule string:
"... < 0,1,2,3,4,5,6,7,8,9 < '?' < '!'"
答案2
得分: 1
在Java 8中,你可以使用两级自定义比较器:
// 给定
List<YourObject> list;
list.sort((o1, o2) -> "?".equals(o1.getName()) ? 1 :
("?".equals(o2.getName()) ? -1 : o1.getName().compareTo(o2.getName())));
这里的排序逻辑是,如果其中一个或另一个名称为 ?
,那么我们始终将该 ?
排在最后。如果两个名称都是 ?
,或者两个名称都不是 ?
,那么我们使用默认的字典序字符串排序。
英文:
In Java 8, you may use a two-tiered custom comparator:
// given
List<YourObject> list;
list.sort((o1, o2) -> "?".equals(o1.getName()) ? 1 :
("?".equals(o2.getName()) ? -1 : o1.getName().compareTo(o2.getName())));
The sorting logic here is that if one or the other names be ?
, then we always sort that ?
last. If both names be ?
, or if neither be ?
, then we sort using the default lexicographical string sorting.
答案3
得分: 1
以下是您要求的代码的中文翻译部分:
您可以使用`java.util.Comparator`中的一些有用方法,使您的生活变得更加轻松,您的代码也不再容易出错,而不需要考虑if-else或三元运算符:
class MyObj {
private String name;
MyObj(String name) {
this.name = name;
}
String getName() {
return name;
}
@Override
public String toString() {
return "name: '" + name + "'";
}
}
public class Demo {
public static void main(String[] args) {
List<MyObj> lst = Arrays.asList(new MyObj("B"), new MyObj("?"), new MyObj("A"));
Comparator<String> questionMarksLast = Comparator
.<String, Boolean>comparing("?".equals)
.thenComparing(Comparator.naturalOrder());
lst.sort(Comparator.comparing(MyObj::getName, questionMarksLast));
System.out.println(lst); // 输出 [{name: 'A'}, {name: 'B'}, {name: '?'}]
}
}
英文:
You can use some useful methods from java.util.Comparator
to make your life easier and your code less error-prone than having to think about if-else or ternary operators:
class MyObj {
private String name;
MyObj(String name) {
this.name = name;
}
String getName() {
return name;
}
@Override
public String toString() {
return "{name: '" + name + "'}";
}
}
public class Demo {
public static void main(String[] args) {
List<MyObj> lst = Arrays.asList(new MyObj("B"), new MyObj("?"), new MyObj("A"));
Comparator<String> questionMarksLast = Comparator
.<String, Boolean>comparing("?"::equals)
.thenComparing(Comparator.naturalOrder());
lst.sort(Comparator.comparing(MyObj::getName, questionMarksLast));
System.out.println(lst); // prints [{name: 'A'}, {name: 'B'}, {name: '?'}]
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论