按降序排列两个数组,一个是双arraylist,另一个是字符串arraylist

时间:2014-01-02 20:27:53

标签: java arrays sorting arraylist

我正在研究两个arraylists来比较两个向量的相似性,一个双数组用于存储相似性值,一个字符串数组用于其索引号。

我用Collections.sort(ArrayList, Collections.reverseOrder())对双数组进行了排序 降序,但不确定如何使用它对索引号进行排序。

我需要的结果是两个数组按降序排列:

Index ArrayList [2,5,7,9],
余弦相似度ArrayList [0.9,0.7,0.5,0.2],

其中索引号2表示值0.9,索引号5表示值0.7,依此类推。

  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);

4 个答案:

答案 0 :(得分:2)

定义一个新的Class,它有两个字段Similarity和Index如下

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;
    }
}

您将只拥有上述对象的一个​​列表,而不是两个列表。

并替换

items1.add(mySimilarity);
index1.add(k);
在您的代码中

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

最后,只需要Collections.sort(list)根据Similarity类中定义的比较器函数对列表进行排序。

答案 1 :(得分:1)

这是将两个数组一起排序的一般解决方案。我相信你可以很容易地使它适应ArrayList而不是数组:

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]];
    }
  }

}

以下是运行上述代码的输出:

$ 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]

答案 2 :(得分:1)

谢谢大家的回复和提示!我最终使用Hashmap和TreeMap而不是ArrayList。 我能够根据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);
       }

答案 3 :(得分:0)

听起来你想要的是一个对象数组。每个对象都有两个属性,索引和相似性。然后,您可以按相似性进行排序,仍然使用sort()方法,但是传入比较器函数,如此

public static void sort(T [] a,             比较器c)

在这里解释得更多 http://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html