简体   繁体   中英

Sorting two arrays in descending order, one is double arraylist, the other is string arraylist

I'm working on two arraylists to compare the similarity of two vectors, one double array for storing similarity values, one string array for its index number.

I sorted the double array with Collections.sort(ArrayList, Collections.reverseOrder()) in decending order, but not sure how the index number will be sorted with it.

The results I need is both arrays in descending order:

Index ArrayList [2, 5, 7, 9],
Cosine Similarity ArrayList [0.9, 0.7, 0.5, 0.2],

where index number 2 refers to value 0.9, index number 5 refers to value 0.7, so on and so forth.

  public void getSimilarity() {
    double mySimilarity;
    //double mrr1;
    List<Double> items1 = new ArrayList<Double>();
    List<String> index1 = new ArrayList<String>();

    for (int i = 0; i < tfidfDocsVector.size(); i++) {
        for (int j = 0; j < tfidfDocsVector.size(); j++) {
           int k = j+1;
   //cosineSimilarity is defined in another file (now shown here)
                     mySimilarity = new Similarity().cosineSimilarity
                                   (tfidfDocsVector.get(i), 
                                     tfidfDocsVector.get(j));
   //store certain vectors only
            if (i==9 && k < 10) {

                        System.out.println("between Query1" + " and " + "string" + k + "  =  "
                              + mySimilarity);
             items1.add(mySimilarity);
             index1.add(k);
                              } 
                         }
    }
    Collections.sort(items1, Collections.reverseOrder());
    //how to sort index1 along with items?
    System.out.println("Ranked values for query1  - Largest to the smallest " + items1);

Define a new Class having two fields Similarity and Index as following

Class Similarity implements Comparable<Similarity> {
    double value;
    int index;
    public Similarity(double value, int index) {
        this.value = value;
        this.index = index;
    }

    @Override
    public int compareTo(Similarity that) {
        if (this.value > that.value)
            return -1;
        else if (this.value < that.value)
            return 1;
        else
            return 0;
    }
}

Instead of two Lists you will have only one List of the above object.

And replace

items1.add(mySimilarity);
index1.add(k);

in your code by:

list.add(new Similarity(mySimilarity, k));

At the very end, just do Collections.sort(list) to sort the list on the basis of the comparator function defined in the Similarity class.

Here's a general solution for sorting two arrays together. I'm sure you could easily adapt it to work with ArrayList rather than arrays:

import java.util.*;

public class Sort2Arrays {

  public static void main(String[] args) {
    // The two arrays we need to sort
    String[] strings = {
      "E",  "D",  "H",  "B",  "F",  "A",  "G",  "C",  "I",  "J"
    };
    Double[] doubles = {
      7.15, 3.57, 1.54, 5.08, 2.99, 3.65, 4.04, 3.70, 7.07, 0.63
    };
    // Sort in reverse based on strings
    sortTogether(strings, doubles, Collections.reverseOrder());
    // Print the results
    System.out.println(Arrays.asList(strings));
    System.out.println(Arrays.asList(doubles));
  }

  public static <X,Y> void sortTogether(final X[] xs, final Y[] ys, final Comparator<X> cmp) {
    // The arrays must be the same length
    assert(xs.length == ys.length);
    // First, we create a new array to track the indices
    Integer[] indices = new Integer[xs.length];
    for (int i=0; i<indices.length; i++) indices[i] = i;
    // Second, we create a comparator to sort the indices array
    // based on the original array that we want (in this case, xs)
    Comparator<Integer> indexCmp = new Comparator<Integer>() {
      @Override public int compare(Integer i1, Integer i2) {
        return cmp.compare(xs[i1], xs[i2]);
      }
    };
    // Third, we sort the indices with the comparator
    Arrays.sort(indices, indexCmp);
    // Finally, we re-order the original arrays based on indices
    X[] xs0 = Arrays.copyOf(xs, xs.length);
    Y[] ys0 = Arrays.copyOf(ys, ys.length);
    for (int i=0; i<indices.length; i++) {
      xs[i] = xs0[indices[i]];
      ys[i] = ys0[indices[i]];
    }
  }

}

Here is the output from running the above code:

$ java Sort2Arrays
[J, I, H, G, F, E, D, C, B, A]
[0.63, 7.07, 1.54, 4.04, 2.99, 7.15, 3.57, 3.7, 5.08, 3.65]

Thank you all for the replies and tips! I ended up using Hashmap and TreeMap instead of ArrayList. I was able to rank the results in descending order based on get.Value().

    public static void printMap(Map<Double, String> map) {
    for (@SuppressWarnings("rawtypes") Map.Entry entry : map.entrySet()) {
        System.out.println(entry.getValue()  + ": " + entry.getKey());
    }
  }



          public void getSimilarity() {
           double mySimilarity;

          List<Double> items1 = new ArrayList<Double>();
          List<String> index1 = new ArrayList<String>();
          Map map1 = new HashMap();

            for (int i = 0; i < tfidfDocsVector.size(); i++) {
            for (int j = 0; j < tfidfDocsVector.size(); j++) {
             int k = j+1;
            //cosineSimilarity is defined in another file (now shown here)
                      mySimilarity = new Similarity().cosineSimilarity
                                            (tfidfDocsVector.get(i), 
                                            tfidfDocsVector.get(j));
             //store certain vectors only
                     if (i==9 && k < 10) {

                    System.out.println("between Query1" + " and " + "string" + k + "  =  "
                          + mySimilarity);
                map1.put(mySimilarity, k); 
                          } 
                     }
        }
             Map<Double, String> treeMap1 = new TreeMap(Collections.reverseOrder());
               treeMap1.putAll(map1);
            System.out.println ("Ranked results similarity measure (most relevant first): ");
    printMap(treeMap1);
       }

It sounds like what you want is an array of objects. Each object would have two properties, Index and Similarity. You can then sort by Similarity, still using the sort() method but passing in a comparator function, like this

public static void sort(T[] a, Comparator c)

explained more here http://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html

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