2012-04-05 143 views
5

我有一个包含双值二维的ArrayList:如何排序二维的ArrayList

ArrayList<ArrayList<Double>> data = new ArrayList<ArrayList<Double>>(); 

与传统阵列的比喻,我想在这个矩阵“的cols”进行排序:我想要在子ArrayLists中获取具有相同索引的项目,然后对它们进行排序。就像为每一列调用Collections.sort()... 按行我的意思是外层和内层是列。

这样做的正确方法是什么? 我想过迭代矩阵来反转它,然后用Collections.sort()对每一行进行排序?但也许这不是最好的解决方案,因为矩阵大约是400 * 7000。

由于矩阵的大小未知,我无法使用经典数组。

感谢您的帮助。

+0

我假设外层代表行,但如果您可以在您的问题中说明它会很好。 – ahanin 2012-04-05 20:30:55

+0

是双打任何具体的数字或只是随机?他们是什么意思? – noMAD 2012-04-05 20:35:14

+0

你看过专门的矩阵库,如[JaMa](http://math.nist.gov/javanumerics/jama/)吗?如果其中一个涵盖了您的要求,它可能会为您节省大量时间。 – Barend 2012-04-05 20:36:54

回答

3

做这样的事情:

final int COLUMN = 5; 
    Comparator<ArrayList<Double>> myComparator = new Comparator<ArrayList<Double>>() { 
     @Override 
     public int compare(ArrayList<Double> o1, ArrayList<Double> o2) { 
      return o1.get(COLUMN).compareTo(o2.get(COLUMN)); 
     } 
    }; 
    Collections.sort(list, myComparator); 

集列到任何列你排序上。

更新:

是的,这根本不起作用。

我喜欢ahanin的第二个建议,使您自己的列表包装您的原始列表。你必须包装get()返回的对象,以便变量wrappedList包含列值,而wrappedList.get(0)也返回一列值。然后排序可以工作。我想知道为了使用Collections.sort()来处理List,必须实现的最小方法是什么。

这可能是最简单的做一个别人的快速排序,并使其与您的列表一起工作。

这是一个实现:http://www.vogella.de/articles/JavaAlgorithmsQuicksort/article.html

+1

OP不要求对特定列进行排序,而是要求独立对列进行排序。 – trutheality 2012-04-05 21:20:08

+0

我的理解是他希望将所有**列进行排序,所以我们实际上必须在列表之间移动Double元素。 – 2012-04-05 21:20:23

+0

@SarelBotha:是的,我想单独对每列进行排序,Collections.sort()应该被调用多次(列数)(内部ArrayLists的大小)。 – Believer 2012-04-05 21:38:14

2

我得到了两个疯狂的想法:要么实现自己的排序算法,这将意识到你的倒置矩阵结构,要么写一个Collection的实现来包装你的结构并表示列,以后可以用作Collections.sort()的参数。使用ArrayList,这应该是相当快的。

0

我猜如果存储不是问题,你可以在ArrayList中使用SortedMap。这样你就不必担心排序元素。

ArrayList<SortedMap<Double,byte>> data; 
+2

这将如何工作?它会按行排序,这不是他想要的。 – noMAD 2012-04-05 20:45:48

+0

我不认为行与列之间有明确的区别。而且它只是一个逻辑显示,只有当你遍历它时才能看到。这一切都取决于所使用的遍历技术。 – 2012-04-05 21:05:33

0

如果我理解正确的。q没有确定,但是这将排序所有的“列”(假设外部级都行内水平都列):

final ArrayList<ArrayList<Double>> data = new ArrayList<ArrayList<Double>>(); 
    //... 

    final Integer[] rows = new Integer[data.size()]; 
    for(int i=0;i<rows.length;i++) 
     rows[i]=i; 

    int cols = data.get(0).size(); 
    for(int c=0;c<cols;c++) 
    { 
     final int colidx = c; 
     Arrays.sort(rows,new Comparator<Integer>(){ 
      @Override 
      public int compare(Integer arg0, 
        Integer arg1) { 
       return data.get(arg0).get(colidx).compareTo(data.get(arg1).get(colidx));   
      }});  

     for(int i=0;i<rows.length;i++) 
      data.get(i).add(colidx+1,data.get(rows[i]).get(colidx)); 
     for(int i=0;i<rows.length;i++) 
      data.get(i).remove(colidx); 
    } 
3

所以,这里有一个选项,就像倒置的想法,但不是颠倒你一次构建一列的整个事物,而是将它整理并丢弃。

ArrayList<ArrayList<Double>> data = new ArrayList<ArrayList<Double>>(); 

for(int c=0; c<data.get(0).size(); c++) { 
    List<Double> col = new ArrayList<Double>(); 
    for(int r=0; r<data.size(); r++) 
     col.add(data.get(r).get(c)); 

    Collections.sort(col); 

    for(int r=0; r<col.size(); r++) 
     data.get(r).set(c, col.get(r)); 
} 

我怀疑你将能得到什么更有效,除了创建自己的类,它提供的名单表的列的观点也许是选项。

0

您必须访问所有元素才能在任何情况下进行排序。所以你可以做的是这个。

int temp[] = new temp[col.length]; 
int x = 0; 
while(x < row.length) 
{ 
    for(int i = 0; i<col.length; i++) 
    { 
     temp[i] = mat[x][i]; 
    } 
    sort(temp); 
    for(int i = 0; i<col.length; i++) 
    { 
     mat[x][i] = temp[i]; 
    } 
x++; 
} 

这里的运行时间将是O(n^2logn)但因为要排序仅有400双打,不会花费太多时间。并且由于必须至少访问矩阵中的每个元素一次,所以不能低于O(n^2)

2

以下是将数据转换为对象数组的这种情况的方法。将列更改为任何你喜欢的。

final int column = 3; 
ArrayList<ArrayList<Double>> data = new ArrayList<ArrayList<Double>>(); 

// Convert data into an object array 
Object [] temp = data.toArray(); 

Arrays.sort(temp, new Comparator<Object>() { 
    @Override 
    public int compare(Object o1, Object o2) { 
     // Get inner arrays to be compared by type-casting 
     ArrayList<Double> temp1 = (ArrayList<Double>) o1; 
     ArrayList<Double> temp2 = (ArrayList<Double>) o2; 

     // Then compare those inner arrays' indexes 
     return temp1.get(column).compareTo(temp2.get(column)); 
    } 
}); 

// Clear the old one and add the ordered list into 
data.clear(); 

for(Object o: temp) 
{ 
    data.add((ArrayList<Double>) o); 
}