java - Sorting of two-dimensional array based on two parameters -
the following code performs 'hierarchical' sorting of two-dimensional matrix. firstly, sorts elements based on values of ranks
. secondly, takes sorted matrix, searches elements have same values of ranks
, , sorts them based on dist
. in descending order.
question 1: possible achieve same result in easier way? tried create comparator
, provided incorrect result particular case.
question 2: how indexes of unsorted elements after sorting?
import java.util.arraylist; public class test { public static void main(string args[]) { arraylist<arraylist<double>> values = new arraylist<arraylist<double>>(); arraylist<double> ranks = new arraylist<double>(); arraylist<double> dist = new arraylist<double>(); ranks.add(8.0); ranks.add(3.0); ranks.add(8.0); ranks.add(1.0); dist.add(1.8); dist.add(2.8); dist.add(1.9); dist.add(2.1); values.add(0,ranks); values.add(1,dist); int len = ranks.size(); arraylist<arraylist<double>> sortedranks = new arraylist<arraylist<double>>(); sortedranks = order(values,0,ranks.size()); boolean swapped = true; int j = 0; double tmp1, tmp2; while (swapped) { swapped = false; j++; (int = 0; < len - j; i++) { double val1 = sortedranks.get(0).get(i); double val2 = sortedranks.get(0).get(i+1); if (val1==val2) { if (sortedranks.get(1).get(i) < sortedranks.get(1).get(i+1)) { tmp1 = sortedranks.get(1).get(i); tmp2 = sortedranks.get(1).get(i+1); sortedranks.get(1).remove(i); sortedranks.get(1).remove(i); sortedranks.get(1).add(i,tmp2); sortedranks.get(1).add(i+1,tmp1); swapped = true; } } } } (int = 0; < len; i++) { system.out.println("ranks " + + " : " + sortedranks.get(0).get(i) + ", distances : " + sortedranks.get(1).get(i)); } } public static arraylist<arraylist<double>> order(arraylist<arraylist<double>> values, int i_start, int i_fin) { boolean swapped = true; int j = 0; int i_rank = 0; int i_dist = 1; double tmp1_rank, tmp2_rank, tmp1_dist, tmp2_dist; while (swapped) { swapped = false; j++; (int = i_start; < i_fin - j; i++) { if (values.get(i_rank).get(i) < values.get(i_rank).get(i+1)) { tmp1_rank = values.get(i_rank).get(i); tmp2_rank = values.get(i_rank).get(i+1); tmp1_dist = values.get(i_dist).get(i); tmp2_dist = values.get(i_dist).get(i+1); values.get(i_rank).remove(i); values.get(i_rank).remove(i); values.get(i_dist).remove(i); values.get(i_dist).remove(i); values.get(i_rank).add(i,tmp2_rank); values.get(i_rank).add(i+1,tmp1_rank); values.get(i_dist).add(i,tmp2_dist); values.get(i_dist).add(i+1,tmp1_dist); swapped = true; } } } return values; } }
the code uses comparator (does not work case):
public class myentry implements comparable<myentry> { private double rank; private double dist; public myentry(double rank, double dist) { this.rank = rank; this.dist = dist; } public static comparator<myentry> valuecomparator = new comparator<myentry>() { public int compare(myentry value1, myentry value2) { double rfirst = value1.rank; double rsecond = value2.rank; double dfirst = value1.dist; double dsecond = value2.dist; if (rsecond != rfirst) { return (int) (rsecond - rfirst); } else { return (int) (dsecond - dfirst); } } }; }
your comperator approach work, has few bugs. first of replace double
s in myentry
double
.
comparing double
not same comparing double
example:
double = 1.0; double b = 1.0; system.out.println(a == b); system.out.println(a.equals(b)); system.out.println(a.doublevalue()== b.doublevalue());
will return
false true true
then in comparison cast int
, implies flooring data. (int) (2 - 1.9)
give 0
better compare using <
, return -1 or 1.
public static comparator<myentry> valuecomparator = new comparator<myentry>() { public int compare(myentry value1, myentry value2) { double rfirst = value1.rank; double rsecond = value2.rank; double dfirst = value1.dist; double dsecond = value2.dist; if (rsecond != rfirst) { return rsecond < rfirst?-1:1; } else if(dsecond!=dfirst){ return dsecond < dfirst ?-1:1; } return 0; } }
for second question require index. done in 2 ways. first option include index in myentry
this:
public class myentry implements comparable<myentry> { private double rank; private double dist; private int index; private static int nextindex = 0; public myentry(double rank, double dist) { this.rank = rank; this.dist = dist; this.index = nextindex++; }
this way able retain index not flexible.
a more flexible approach have index in separate array, , sort that.
class indexedarraycomparator implements comparator<integer>{ myentry[] array; public indexedarraycomparator(myentry[] entries){ this.array=entries; } public integer[] createindexes(){ integer[] index = new integer[array.length]; for(int =0;i<index.length;i++){ index[i]=i; } return index; } public int compare(integer i0, integer i1) { double rfirst = array[i0].rank; double rsecond = array[i1].rank; double dfirst = array[i0].dist; double dsecond = array[i1].dist; if (rsecond != rfirst) { return rsecond > rfirst?-1:1; } else if(dsecond!=dfirst){ return dsecond > dfirst ?-1:1; } return 0; } }
you can use this:
myentry[] entries = new myentry[5]; entries[0]= new myentry(1.1,5); entries[1]= new myentry(1.1,4); entries[2]= new myentry(2.1,5); entries[3]= new myentry(0.1,3); entries[4]= new myentry(3.1,1); indexedarraycomparator comp = new indexedarraycomparator(entries); integer[] index = comp.createindexes(); arrays.sort(index,comp); for(int =0;i<index.length;i++){ myentry e = entries[index[i]]; system.out.println(string.format("%2d:r= %3.1f, d= %3.1f" ,index[i],e.rank,e.dist)); }
which give:
3:r= 0.1, d= 3.0 1:r= 1.1, d= 4.0 0:r= 1.1, d= 5.0 2:r= 2.1, d= 5.0 4:r= 3.1, d= 1.0
the second way of sorting while maintaining index described here. credits jon skeet
Comments
Post a Comment