根据另一个列表的值对列表进行排序 - Java

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4839915/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 08:16:27  来源:igfitidea点击:

Sorting a list based on another list's values - Java

javasorting

提问by FILIaS

One list with names:(unsorted) e.g [paul, foul, mark]

一份带有姓名的列表:(未分类)例如[paul, foul, mark]

Another list with integers: e.g [5, 2, 6]

另一个整数列表:例如 [5, 2, 6]

The values on the second list are the numbers "selected" by each person(name), so paul has number 5, foul's number is 2, mark's number is 6.

第二个列表中的值是每个人(姓名)“选择”的数字,所以保罗的数字是 5,犯规的数字是 2,马克的数字是 6。

I'm trying to sort the names' list based on the values of the second list on a descending order. I cant use a map as i need both lists on other occasions on my program.

我正在尝试根据第二个列表的值按降序对名称列表进行排序。我不能使用地图,因为我在程序的其他场合需要两个列表。

With the sorting method i did i geta list like that: [paul, mark, foul]

使用排序方法,我得到了一个这样的列表: [paul, mark, foul]

As you can see, its not sorted as i would want.

正如你所看到的,它没有按照我想要的方式排序。

The correctone would be: [mark,paul,foul]

正确的一个是: [大关,保罗犯规]

But i cant find the fault on the code.

但我找不到代码上的错误。

public ArrayList<String> sortNames(ArrayList<Integer> results){
    String tmp;
    for (int k=0; k<Names.size()-1; k++) {

        boolean isSorted=true;
        for (int i=1; i<Names.size()-k; i++) {

             if (results.get(i)>results.get(i-1)  ) {

                tmp=Names.get(i);
                Names.set(i,Names.get(i-1));
                Names.set(i-1,tmp);

                isSorted=false;
            }
        }
        if (isSorted) break;
    }
    return Names;

}

EDIT!!! with the help of the answers below,the code is:

编辑!!!在以下答案的帮助下,代码是:

    public ArrayList<String> sortNames(ArrayList<Integer> results){
        String tmp2;
        int tmp;
        for (int k=0; k<Names.size()-1; k++) {

            boolean isSorted=true;
            for (int i=1; i<Names.size()-k; i++) {

                 if (results.get(i)>results.get(i-1)  ) {
                     tmp=results.get(i);
                     results.set(i,results.get(i-1));
                     results.set(i-1,tmp);


                    tmp2=Names.get(i);
                    Names.set(i,Names.get(i-1));
                    Names.set(i-1,tmp2);

                    isSorted=false;
                }
            }
            if (isSorted) break;
        }
    return Names;

}

This code works properly(for small lists) I've just the query why it doesnt work for objects like ImageIcon. Any ideas?

这段代码工作正常(对于小列表)我只是查询为什么它不适用于像 ImageIcon 这样的对象。有任何想法吗?

回答by camickr

Get rid of the two Lists. If the data is related then the data should be stored together in a simple class. Then the entire class is added to a list where you can sort on the individual properties if required. You can use a Bean Comparatorto sort this List however you desire.

摆脱这两个列表。如果数据是相关的,那么数据应该一起存储在一个简单的类中。然后整个类被添加到一个列表中,如果需要,您可以在其中对各个属性进行排序。您可以根据需要使用Bean Comparator对该列表进行排序。

回答by maaartinus

You're sort of sorting the List Names based on values of the List results... and it only terminates because of the condition k<Names.size()-1. Such a condition is usually not needed at all in bubblesort, which shows that there's something wrong.

您正在根据 List 结果的值对 List Names 进行排序......它仅因条件而终止k<Names.size()-1。在冒泡排序中通常根本不需要这样的条件,这表明有问题。

You'd have to swap elements in both lists, not only in Names. This is the answer, but be warned that bubblesort is one of the worst algorithms ever.

您必须交换两个列表中的元素,而不仅仅是在 Names 中。这就是答案,但请注意,冒泡排序是有史以来最糟糕的算法之一。

Edit:

编辑:

I cant use a map as i need both lists on other occasions on my program.

我不能使用地图,因为我在程序的其他场合需要两个列表。

For sure you can (assuming the numbers are unique):

你肯定可以(假设数字是唯一的):

Map<Integer, String> m = new HashMap<Integer, String>();
for (int i=0; i<results.size(); ++i) m.put(results.get(i), Names.get(i));
Collections.sort(results);
for (int i=0; i<results.size(); ++i) Names.set(i, m.get(results.get(i));

There may be errors, but the idea should be clear.

可能有错误,但思路应该清晰。

There's another solution using a class of pairs (result, name), which works even with non-unique numbers, if you need it.

还有另一种使用一组对(结果,名称)的解决方案,如果需要,它甚至适用于非唯一数字。

A slightly shorter solution:

一个稍短的解决方案:

Map<Integer, String> m = new TreeMap<Integer, String>();
for (int i=0; i<results.size(); ++i) m.put(results.get(i), Names.get(i));
Names.clear();
Names.addAll(m.values());

This is based on properties of TreeSet.values"The collection's iterator returns the values in ascending order of the corresponding keys" and List.addAll"Appends all of the elements in the specified collection to the end of this list, in the order that they are returned by the specified collection's iterator"

这是基于性能TreeSet.values集合的迭代器在提升相应的键的顺序返回值”和List.addAll追加所有指定集合中的元素到此列表的末尾,在以使他们由指定集合的​​迭代器返回

回答by Karl Knechtel

  1. Build a list of pairs of (name, value) by taking elements from the two lists pairwise (having a class that stores the two values as fields). Implement Comparable to compare the value field.

  2. Sort the result with Collections.sort().

  3. Extract the names from the sorted list.

  1. 通过从两个列表中成对获取元素(具有一个将两个值存储为字段的类)来构建一个 (name, value) 对列表。实现 Comparable 以比较值字段。

  2. 用 对结果进行排序Collections.sort()

  3. 从排序列表中提取名称。

回答by miah

Create a temporary mapping name->number, then sort names with custom comparator which uses the mapping:

创建一个临时映射 name->number,然后使用使用映射的自定义比较器对名称进行排序:

Map<String, Integer> m = new HashMap<String, Integer>;
for(int i = 0; i < Names.size(); i++)
    m.put(Names.get(i), results.get(i));
Collections.sort(Names, new Comparator<String>() {
    @Override
    public int compare(String s1, s2) { return m.get(s2) - m.get(s1); }
});

This solution will work even if some numbers are equal.

即使某些数字相等,此解决方案也将起作用。

回答by bestsss

There you go w/ the vanilest quicksort you'd ever get, the simplest principle is: when you swap the 1st list, swap the 2nd as you go. Hopefully that's not a homework, but even if it's not... In short, copy/paste and enjoy the quickSort(list1, list2)is all you need. The lists are sorted by the 1st list natural oredering define by Comparable.

您可以使用您曾经获得的最普通的快速排序,最简单的原则是:当您交换第一个列表时,请随时交换第二个列表。希望这不是家庭作业,但即使不是......简而言之,复制/粘贴并享受它quickSort(list1, list2)就是你所需要的。列表按第一个列表的自然顺序排序Comparable

private static void swap(List<?> l1, List<?> l2, int i, int j){
    Collections.swap(l1, i, j);
    Collections.swap(l2, i, j);     
}
private static <T extends Comparable<? super T>>  int partition(List<T> comp, List<?> l2, int left, int right){
    int i = left, j = right;
    T pivot = comp.get((left + right) / 2);

    while (i <= j) {
        while (comp.get(i).compareTo(pivot)<0)
            i++;

        while (comp.get(i).compareTo(pivot)>0)
            j--;

        if (i <= j) {
            swap(comp, l2, i++, j--);
        }
    };
    return i;
}
private <T extends Comparable<? super T>>  void quickSort(List<T> comp, List<?> l2, int left, int right) {
    int index = partition(comp, l2, left, right);

    if (left < index - 1)
        quickSort(comp, l2, left, index - 1);

    if (index < right)
        quickSort(comp, l2, index, right);
}

public <T extends Comparable<? super T>>  void quickSort(List<T> comp, List<?> l2) {
    if (comp.size()<l2.size())
        throw new IndexOutOfBoundsException();
    quickSort(comp, l2, 0, comp.size());
}