【问题标题】:How sort a string array based on the location of a word that the first string contains in a second string array, android, java如何根据第一个字符串在第二个字符串数组中包含的单词的位置对字符串数组进行排序,android,java
【发布时间】:2016-05-05 01:58:07
【问题描述】:

我正在尝试对用于列表视图的字符串数组进行排序。我有两个字符串数组,一个是我想要显示的单词,另一个是我想要的排序顺序。任何不在排序列表中的单词都可能在最后。例如:

String[] order = {"Paperclip", "Pencil", "Earphones", "Pen"};
String[] displaylist = {"Pencil 1", "Pen 1", "Dog 1", "Earphones 1", "Pen 2", "Paperclip 1", "Pencil 2", "Pen 3", "Earphones 2"};

我希望之后对显示列表进行排序的方式是:

String[] displaylistsorted = {"Paperclip 1", "Pencil 1", "Pencil 2", "Earphones 1", "Earphones 1", "Earphones 2", "Pen 1", "Pen 2", "Pen 3", "Dog 1"}

我希望能够在排序后将列表保持在同一个案例中。

我浏览了很多不同的教程和其他自定义比较器的堆栈问题,但我的 Java 初级知识最终迫使我在这里写一个问题。

非常感谢您的帮助!

【问题讨论】:

  • 欢迎来到 StackOverflow!目前,您的问题过于宽泛 - 有很多可能的方法可以实现您想要的。缩小问题范围的一个好方法是包含您已经尝试过的内容 - 这样我们就可以解释哪些部分需要更正以及原因。
  • 我在很多不同的地方阅读过,但我找不到与我想要做的事情相匹配的例子。对不起,它太宽泛了。也许下次我问一个问题时,我会比现在知道的更多。

标签: java android arrays sorting comparable


【解决方案1】:

您遍历一组单词并将它们与搜索词数组逐一进行比较。如果找到匹配项,则将列表中的单词添加到该术语的惰性创建匹配列表中。

如果你完成了这个集合,你可以按照搜索词的顺序加入结果列表,并在最后添加剩余的词。

    List<String>[] results = new List[order.length];
    LinkedList<String> remainders = new LinkedList<String>();

    for (String word : displaylist) {
        boolean found = false;
        for(int i=0; i<order.length; i++) {
            if(word.contains(order[i])) {
                if(results[i] == null) results[i] = new LinkedList<String>();
                results[i].add(word);
                found = true;
                break;
            }
        }

        if( !found ) {
            remainders.add(word);
        }
    }

    List<String>theResult = new ArrayList<String>(displaylist.length);
    for ( List<String>result : results) {
        if( result != null ) theResult.addAll(result);
    }

    theResult.addAll(remainders);

【讨论】:

  • 谢谢!但我收到一个错误:java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object[] java.util.Collection.toArray()' on an null object reference
  • 如果您更具体地了解您发现错误的位置,将会很有帮助。通过惰性列表创建,并非results 的所有元素都保证为非空。最后的组合循环需要一个空检查。我已经添加了。
  • 谢谢!那解决了它。这确定包括显示列表中的所有项目吗?
  • 是什么让你觉得缺少了什么?
  • 我有一个很长的项目清单,我无法将它们全部检查一遍。有没有可能这不包括所有这些?还是只是将它们添加到末尾?
【解决方案2】:

您说的是自定义比较器...使用 String 方法直接比较数组的内容可能是一种更直接的解决方案。但是,出于学术目的,使用自定义比较器意味着使用 class 来解决您的问题。在 Java 中创建自定义比较器需要您实现 Comparable 接口。这实际上意味着您的类将需要实现方法compareTo 方法:

class MyClass implements Comparable {
   ...
   @Override
   public int compareTo(Object o) {
       ...
   }
}

当您覆盖compareTo 时,您决定是什么让一个对象“大于”或“小于”另一个对象。如果一个对象“大于”另一个对象,您的自定义方法应该返回 1。如果它“小于”另一个对象,它应该返回 -1。如果相等,则应返回 0。“大于”或“小于”表示对象应如何排序。

据我所知,order 数组中的元素与将被调用以帮助排序的元素的开头相匹配,例如"Paperclip 1""Paperclip" 开头。假设这是真的,适​​当的compareTo 方法可以使用startsWith 来决定适当的顺序:

class MyClass implements Comparable {
    private static final String order[] = {"Paperclip", "Pencil", "Earphones", "Pen"};
    private String value;
    ...
    @Override
    public int compareTo(Object o) {
        MyClass that = (MyClass)o;
        int thisRank = 0;
        int thatRank = 0;
        for (String ord : order) {
            if (this.value.startsWith(ord)) {
                thisRank = count;
            }
            if (that.value.startsWith(ord)) {
                thatRank = count;
            }
            count++;
        }
        if (thisRank > thatRank) return 1;
        if (thisRank < thatRank) return -1;
        return 0;
    }
}

然后,您需要使用新类创建某种集合,然后对其进行排序:

MyClass displayList[] = { new MyClass("Pencil 1"), new MyClass("Pen 1"),
    new MyClass("Dog 1"), ... }
Arrays.sort(displayList);

TreeSet<MyClass> displayList = new TreeSet<>();
displayList.add(new MyClass("Pencil 1"));
displayList.add(new MyClass("Pen 1"));
...

Arrays.sort 使用您的compareTo 方法对数组进行正确排序。 TreeSet 也一样;每次插入新元素时它都会调用compareTo

【讨论】:

  • 为什么要为每个对象创建一个类?您可以将比较代码放入 Comparator 对象中。
  • 我想这是真的......问题提到了比较器,所以我只是用类来整理一个例子。
猜你喜欢
  • 1970-01-01
  • 2021-10-30
  • 2016-05-25
  • 1970-01-01
  • 1970-01-01
  • 2021-07-06
  • 1970-01-01
  • 1970-01-01
  • 2022-11-15
相关资源
最近更新 更多