开发者

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

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

Another list with integers: e.g [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.

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 get a list like that: [paul, mark, foul]

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

The correct one 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?


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 Comparator to sort this List however you desire.


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.

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.

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"


  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.


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.

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());
}


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

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜