I am trying to sort (decreasing) an array of integers but keeping track of the original index.
I mean, for example if I have this array:
b[
Try sorting pairs of (value, index)
compared by value:
public class Pair implements Comparable<Pair> {
public final int index;
public final int value;
public Pair(int index, int value) {
this.index = index;
this.value = value;
}
@Override
public int compareTo(Pair other) {
//multiplied to -1 as the author need descending sort order
return -1 * Integer.valueOf(this.value).compareTo(other.value);
}
}
Then, when you're going to sort:
public static void main(String[] args) {
Pair[] yourArray = new Pair[10];
//fill the array
yourArray[0] = new Pair(0, 5); yourArray[1] = new Pair(1, 10); //and so on
Arrays.sort(yourArray);
}
Now, you have an array of Pair
object ordered by value
descending. Each object also contains index
- the place in the original array.
P. S. I wrote the sample in Java as the question has java
tag. Although, in C++
the idea is the same, only the implementation is a little bit different.
The following answer provides the main steps to overcome the issue explained in the question without details code provided.
Class
that has two attributes value
and index
. where value
is the original attribute value and index
is the position before sorting.ArrayList
of this Class
.Class
with the wanted value
and index
.Note: one possible way to set the index
value is to iterate through the Arraylist
and set the value of index
using loop index.
sort the Arraylist
using specialComparable
based on value
attribute.
now after sorting you can know the previousindex
of any entry by invoking its index
attribute.
The OP poster's example involved sorting an array of integer. If any of the readers have a similar situation, but with an array of non-primitive types, the following is a class that handles this for arrays of non-primitives. The class takes a somewhat different approach. It leaves the original array unmodified but instead creates an array of indexes and sorts and returns that.
public class IndirectSorter<T extends Comparable<T>> {
public int[] sort(T args[]) {
Integer origindex[] = new Integer[args.length];
int retval[] = new int[args.length];
for (int i=0; i<origindex.length; i++) {
origindex[i] = new Integer(i);
}
Arrays.sort(origindex, new IndirectCompareClass<T>(args));
for (int i=0; i<origindex.length; i++) retval[i] = origindex[i].intValue();
return retval;
}
class IndirectCompareClass<T extends Comparable<T>> implements Comparator<Integer> {
T args[];
public IndirectCompareClass(T args[]) { this.args = args; }
public int compare( Integer in1, Integer in2 ) {
return args[in1.intValue()].compareTo(args[in2.intValue()]);
}
public boolean equals( Integer in1, Integer in2 ) {
return args[in1.intValue()].equals(args[in2.intValue()]);
}
}
}
And to call it quickly you can do something like this:
public static void main(String args[] ) {
int indexes[] = new IndirectSorter<String>().sort(args);
for (int i : indexes) {
System.out.printf("original pos: %d %s\n", i, args[i] );
}
}
Edit: If you're willing to reimplement the Arrays.sort(int[]) method, you can avoid the creation and use of Integer objects. This can be appealing.