简体   繁体   中英

Sort a list based on index of another list values

I am trying to use a comparator to sort my List 2 based on List 1.

So the two lists are:

ListA = [2,3,4]
ListB = [8,2,4]

I need to sort list 2 based on list 1.

Expected output:

List1: [2,3,4]
List2: [2,8,4]

Here is the code I am trying

Collections.sort(list1);
Collections.sort(list2,new Comparator<Integer>(){
    public int compare(Integer left,Integer right){
        return Integer.compare(list1.indexOf(left),list1.indexOf(right));
    }
})

Here sorting will be based on index of List1 elements. The comparator above is not working for me Please help?

It's not exactly clear to me from your example what you're trying to do, so this answer might not actually address your question. If what you're trying to do is to apply the sort-order of ListA to both ListA and ListB then you can do it as follows.

Create an auxiliary class that allows you to pair up the two lists with respect to the same index:

private class IntPair implements Comparable<IntPair> {
    int i1;
    int i2;

    public IntPair(int i1, int i2) {
        this.i1 = i1;
        this.i2 = i2;
    }

    public int compareTo(IntPair other) {
        return Integer.compare(i1, other.i1);
    }
}

Then create a new list of IntPair instances from your original lists and sort it.

int size = list1.size();
List<IntPair> aux = new ArrayList(size);
for (int i = 0; i < size; i++) {
    aux.add(new IntPair(list1.get(i), list2.get(i)))
}

Collections.sort(aux);

Finally, copy back the values of the resulting pair list onto your original lists.

for (int i = 0; i < size; i++) {
    IntPair ip = aux.get(i);
    list1.set(i, ip.i1);
    list2.set(i, ip.i2);
}

Note that in terms of algorithmic complexity, this approach still is O(nlogn) .

This might be a little heavy-weight, but it gets the job done and it's generic.

Essentially, you can zip-up two lists, sort/compare them based off an index, unzip them, and return the result.

This does not modify the list in-place. I tried to give the variables meaningful, but discreet names. Please acknowledge me for clarification.

import java.util.*;

public class SortUtil {
    public static void main(String[] args) {
        List<Integer> indicies = Arrays.asList(3, 2, 4);
        List<Integer> values   = Arrays.asList(8, 2, 4);
        List<Integer> sorted   = doSort(indicies, values, new TupleComparator<Integer>(0, 1) {
            @Override
            public int doCompare(Integer valueA, Integer valueB) {
                return Integer.compare(valueA, valueB);
            }
        });

        System.out.println(sorted); // [2, 8, 4]
    }

    public static List<Integer> doSort(List<Integer> listA, List<Integer> listB, TupleComparator<Integer> comparator) {
        List<Tuple<Integer>> tuples = zip(listA, listB);
        Collections.sort(tuples, comparator);
        return unzip(tuples, comparator.getValuePos());
    }

    private static <E> List<E> unzip(List<Tuple<E>> tuples, int index) {
        List<E> list = new ArrayList<E>();
        for (Tuple<E> tuple : tuples) {
            list.add(tuple.getData().get(index));
        }
        return list;
    }

    private static <E> List<Tuple<E>> zip(List<E> listA, List<E> listB) {
        List<Tuple<E>> listC = new ArrayList<Tuple<E>>();
        for (int i = 0; i < listA.size(); i++) {
            listC.add(new Tuple<E>(Arrays.asList(listA.get(i), listB.get(i))));
        }
        return listC;
    }

    private static abstract class TupleComparator<E> implements Comparator<Tuple<E>> {
        private int indexPos;
        private int valuePos;
        public TupleComparator(int indexPos, int valuePos) {
            this.indexPos = indexPos;
            this.valuePos = valuePos;
        }
        public int compare(Tuple<E> left, Tuple<E> right) {
            E indexA = left.getData().get(this.getIndexPos());
            E indexB = right.getData().get(this.getIndexPos());
            return doCompare(indexA,  indexB);
        }
        public int getIndexPos() { return indexPos; }
        public int getValuePos() { return valuePos; }
        public abstract int doCompare(E valueA, E valueB);
    }

    private static class Tuple<T> {
        private List<T> data;
        public Tuple(List<T> data) { this.data = data; }
        public List<T> getData() {return data; }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM