Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
176 views
in Technique[技术] by (71.8m points)

arrays - How do I sort a list and use its changed indexes to sort another list in java?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Method 1 (extract indexes first and construct new list)

If you can change the data format and use a custom object, I recommend to use method 2.

You can first extract the indexes of the original elements in at into an array sortedIndices. If the list is already sorted, the value would be [1, 2, 3, ..., n-1]. If the first two elements need to be swapped, the value would be [1, 0, 2, 3, ..., n-1]. Afterwards, you can construct and populate the two sorted lists (btSorted/prcSorted) by adding the elements according to the position stored sortedIndices[i].

ArrayList<Integer> at = new ArrayList<>(Arrays.asList(2, 0, 2, 3, 4));
ArrayList<Integer> bt = new ArrayList<>(Arrays.asList(2, 1, 3, 5, 4));
ArrayList<String> prc = new ArrayList<>(Arrays.asList("p1", "p2", "p3", "p4", "p5"));

// get indexes of a sorted 'at' list
int[] sortedIndices = IntStream.range(0, at.size())
        .boxed().sorted(Comparator.comparing(at::get))
        .mapToInt(x -> x).toArray();

// sort 'bt' according to 'at'
ArrayList<Integer> btSorted = new ArrayList<>();
for (int i = 0; i < sortedIndices.length; i++) {
    btSorted.add(bt.get(sortedIndices[i]));
}

// sort 'prc' according to 'at'
ArrayList<String> prcSorted = new ArrayList<>();
for (int i = 0; i < sortedIndices.length; i++) {
    prcSorted.add(prc.get(sortedIndices[i]));
}

// sort 'at' directly (just for inspection)
ArrayList<Integer> atSorted = new ArrayList<>(at);
Collections.sort(atSorted);

System.out.println("idx: " + Arrays.toString(sortedIndices));
System.out.println("at:  " + at + " => " + atSorted);
System.out.println("bt:  " + bt + " => " + btSorted);
System.out.println("prc: " + prc + " => " + prcSorted);

Output:

idx: [1, 0, 2, 3, 4]
at:  [2, 0, 2, 3, 4] => [0, 2, 2, 3, 4]
bt:  [2, 1, 3, 5, 4] => [1, 2, 3, 5, 4]
prc: [p1, p2, p3, p4, p5] => [p2, p1, p3, p4, p5]

Method 2 (custom class and Comparator)

Much more readable would be to store the data in a custom class (e.g. DataEntry). Then, you can easily sort the array of objects (e.g. data) without resorting to hard to read code:

ArrayList<DataEntry> data = new ArrayList<>();
data.add(new DataEntry(2, 2, "p1"));
data.add(new DataEntry(0, 1, "p2"));
data.add(new DataEntry(2, 3, "p3"));
data.add(new DataEntry(3, 5, "p4"));
data.add(new DataEntry(4, 4, "p5"));

// sort data by 'at'
data.sort(Comparator.comparing(d -> d.at));

// print result
data.forEach(d -> System.out.println(d.at + ", " + d.bt + ", " + d.prc));

Output:

0, 1, p2
2, 2, p1
2, 3, p3
3, 5, p4
4, 4, p5

DataEntry class for reference:

static class DataEntry {
    int at;
    int bt;
    String prc;

    public DataEntry(int at, int bt, String prc) {
        this.at = at;
        this.bt = bt;
        this.prc = prc;
    }
}

Method 3 (with indexOf and Comparator)

This is only stable when there are no duplicates in the lists to be sorted (bt/prc) since indexOf always returns the index of the first occurrence of the specified element in a list (or -1).

Sorting the lists could be done with a custom Comparator and indexOf. We can refer to the values in at at the respective position of the current element being compared (d) in the other lists (bt/prc) in order to sort them:

ArrayList<Integer> at = new ArrayList<>(Arrays.asList(2, 0, 2, 3, 4));
ArrayList<Integer> bt = new ArrayList<>(Arrays.asList(2, 1, 3, 5, 4));
ArrayList<String> prc = new ArrayList<>(Arrays.asList("p1", "p2", "p3", "p4", "p5"));

// sort 'bt' according to 'at'
ArrayList<Integer> btSorted = new ArrayList<>(bt);
btSorted.sort(Comparator.comparing(d -> at.get(bt.indexOf(d))));

// sort prc according to 'at'
ArrayList<String> prcSorted = new ArrayList<>(prc);
prcSorted.sort(Comparator.comparing(d -> at.get(prc.indexOf(d))));

// sort 'at' (just for inspection)
ArrayList<Integer> atSorted = new ArrayList<>(at);
Collections.sort(atSorted);

// print result
System.out.println(at + " => " + atSorted);
System.out.println(bt + " => " + btSorted);
System.out.println(prc + " => " + prcSorted);

Output:

at:  [2, 0, 2, 3, 4] => [0, 2, 2, 3, 4]
bt:  [2, 1, 3, 5, 4] => [1, 2, 3, 5, 4]
prc: [p1, p2, p3, p4, p5] => [p2, p1, p3, p4, p5]

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...