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

后端 未结 5 968
梦如初夏
梦如初夏 2020-12-10 18:58

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

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

The values on the secon

相关标签:
5条回答
  • 2020-12-10 19:10
    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.

    0 讨论(0)
  • 2020-12-10 19:15

    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());
    }
    
    0 讨论(0)
  • 2020-12-10 19:17

    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"

    0 讨论(0)
  • 2020-12-10 19:24

    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.

    0 讨论(0)
  • 2020-12-10 19:28

    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 讨论(0)
提交回复
热议问题