【问题标题】:Sort ArrayList by search keyword按搜索关键字对 ArrayList 进行排序
【发布时间】:2021-10-29 07:40:37
【问题描述】:

我有一个包含这个值的 ArrayList

"Babel"
"Isabelle"
"Elon"
"Eloise"

我在搜索中输入“el”,我对列表进行排序,我希望得到这个结果

"Eloise"
"Elon"
"Babel"
"Isabelle"

因为"Eloise" 以我的搜索开头"el" 就像"Elon" 然后"Babel" 因为按字母顺序排列在"Isabelle" 之前

我不知道如何按数组的第一个字符排序,我尝试对名称进行子字符串化

  users.sort((o1, o2) -> {
                         String name1 = o1.getNickname();
                         String name2 = o2.getNickname();
                         if (o1.getNickname().length() >= finalS.length()) {
                               name1 = o1.getNickname().substring(0, finalS.length());
                         }
                         if (o2.getNickname().length() >= finalS.length()) {
                               name2 = o2.getNickname().substring(0, finalS.length());
                         }
                         return name1.compareTo(name2);
                        });

但这 return name1.compareTo(name2); 比较切割的字符串并按字母顺序排列。 我尝试将其添加到子字符串下方

   if (name1.contains(finalS)) return 1;

    if (name2.contains(finalS)) return 1;

没什么用 Babel 总是在第一位

【问题讨论】:

  • 它不包含您的搜索吗?记住!这是排序!不过滤
  • @Selvin 我只是将其从列表中删除
  • 再次,排序无法删除
  • @Selvin 是的,我知道我在排序之前就这样做了
  • 您在 sort 中有 4 个选择 ... 1. 都以搜索开头 - 返回比较 2.(3.) 只有第一个(第二个)以搜索开头 - 返回 1 (-1) 4。非从搜索开始-返回比较...这不是火箭科学...

标签: android sorting collections


【解决方案1】:

在大多数情况下,Comparator 接口中的工厂方法是合适的,可以减少对比较器的两个参数应用操作的冗余。

由于您的输入是 "el",但名称以大写字母开头,您需要不区分大小写的部分匹配,然后按字符串的自然顺序排序。

List<String> users = Arrays.asList("Babel", "Isabelle", "Elon", "Eloise");
String finalS = "el";

users.sort(Comparator.comparing(
    (String u) -> !finalS.regionMatches(true, 0, u, 0, finalS.length()))
    .thenComparing(Comparator.naturalOrder()));

users.forEach(System.out::println);
Eloise
Elon
Babel
Isabelle

因为显然有一个类 UserNickname 属性要比较,所以完整的排序代码如下所示

users.sort(Comparator.comparing(User::getNickname, Comparator.comparing(
    (String u) -> !finalS.regionMatches(true, 0, u, 0, finalS.length()))
    .thenComparing(Comparator.naturalOrder())));

【讨论】:

    【解决方案2】:

    您的 Comparator 应该如下所示: 首先对以您的搜索开头的那些进行排序,然后对仅包含它们的那些进行排序。但最好的搜索方式是使用 diff-match-patch (https://github.com/google/diff-match-patch)。

     public int compare(User o1, User o2) {
        String search = YOUR_SEARCH.toLowerCase();
        String name1 = o1.getNickname().toLowerCase();
        String name2 = o2.getNickname().toLowerCase();
    
        int i = Boolean.compare(name2.startsWith(search), name1.startsWith(search));
        if (i != 0)
          return i;
        i = Boolean.compare(name2.contains(search), name1.contains(search));
        if (i != 0)
          return i;
        return name2.compareTo(name1);
      }
    

    【讨论】:

    • 因为他已经过滤了不包含search的那个,这可以简化为int i = Boolean.compare(name2.startsWith(search), name1.startsWith(search)); return i == 0 ? name2.compareTo(name1) : i; ...但无论如何都是好的答案...
    猜你喜欢
    • 2014-06-08
    • 2020-04-27
    • 2011-09-24
    • 2017-05-22
    • 2012-11-27
    • 2013-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多