Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 基于第一列对二维数组进行排序_Java_Arrays_Sorting - Fatal编程技术网

Java 基于第一列对二维数组进行排序

Java 基于第一列对二维数组进行排序,java,arrays,sorting,Java,Arrays,Sorting,我读过很多stackoverflow的帖子和一些谷歌搜索结果,但还没有找到完美的东西 基本上,我有一个二维数组,第一行有pointsinteger和一个整数来标识点属于哪个运行。我希望根据点对数组进行排序,但排序时不要丢失标识符 写那个排序码的捷径是什么 之前: 之后: 这不是最好的例子,但我希望您能理解这一点。不幸的是,Java的集合库缺少对并行数组进行排序的方法。创建一个类来保存跑步记录,使用带有自定义比较器的类库对其进行排序,然后将数据放回数组中: public class Run {

我读过很多stackoverflow的帖子和一些谷歌搜索结果,但还没有找到完美的东西

基本上,我有一个二维数组,第一行有pointsinteger和一个整数来标识点属于哪个运行。我希望根据点对数组进行排序,但排序时不要丢失标识符

写那个排序码的捷径是什么

之前:

之后:


这不是最好的例子,但我希望您能理解这一点。

不幸的是,Java的集合库缺少对并行数组进行排序的方法。创建一个类来保存跑步记录,使用带有自定义比较器的类库对其进行排序,然后将数据放回数组中:

public class Run {
    public int points;
    public int runId;
}

Run[] runs = new Run[points[0].length];
for (int i = 0 ; i != runs.length ; i++) {
    Run r = new Run();
    r.points = points[0][i];
    r.runId = points[1][i];
    runs[i] = r;
}
Arrays.sort(runs, new Comparator<Run>() {
    public int compare(Run a, Run b) { 
        return -Integer.compare(a.points, b.points);
    }
});
for (int i = 0 ; i != runs.length ; i++) {
    points[0][i] = runs[i].points;
    points[1][i] = runs[i].runId;
}

.

好的,所以通常我建议使用排序的映射/数组列表,但如果这不是一个选项

像在第一行运行任何其他算法一样,运行正常的排序算法。但是,如果必须进行交换,则只需以相同的方式同时交换第二行的值,例如:

//loop through int i

if(points[i][0] < points[i+1][0]){
    int temp = points[i][0];
    points[i][0] = points[i + 1][0];
    points[i+1][0] = temp;

    temp = points[i][1];
    points[i][1] = points[i + 1][1];
    points[i+1][1] = temp;
}

又好又简单

使用简单的选择排序:

public static void test()
{
        Integer points[][] = 
                {
                  { 12, 13, 10, 0, 0, 0 },
                  { 1, 2, 3, 4, 5, 6 },      
                };
        selectionSort(points[0], points[1]);
        System.out.println(Arrays.toString(points[0]));
        System.out.println(Arrays.toString(points[1]));
}

private static void swap(Integer[] arr, Integer[] arr2, int i, int minIndex)
{
    int tmp = arr[i];
    arr[i] = arr[minIndex];
    arr[minIndex] = tmp;

    tmp = arr2[i];
    arr2[i] = arr2[minIndex];
    arr2[minIndex] = tmp;       
}

// Use any sorting algorithm you like, just keep the swap method.
public static void selectionSort(Integer[] arr, Integer[] arr2) 
{
    int i, j, minIndex;
    int n = arr.length;
    for (i = 0; i < n - 1; i++) 
    {
        minIndex = i;

        for (j = i + 1; j < n; j++)
            if (arr[j] > arr[minIndex])
                minIndex = j;

        if (minIndex != i) 
        {
            swap(arr, arr2, i, minIndex);
        }
    }
}

您能否交换索引,即将示例中的2x6数组存储为6x2数组,并通过点[y][x]而不是点[x][y]对其进行索引

如果是这样,您可以将常规排序函数与自定义比较器一起使用,该比较器比较每个子数组中的第一个元素:

Arrays.sort(points, new Comparator<int[]>() {
    @Override
    public int compare(int[] o1, int[] o2) {
        return o2[0] - o1[0];
    }
});
由于不需要手动交换所有依赖行中的元素,因此这也会运行得更快

因此,如果您可以在不影响其他主要性能的情况下重新构造代码的其余部分以适应排序,我会这样做


否则,您可能必须像其他答案中建议的那样实现手动排序,或者您可以在排序之前和之后转置数组,尽管我怀疑这会更快。

IMHO,好的方法是只对索引进行排序,但使用一个自定义比较器来比较值。这只是与安德里亚提出的建议略有不同。不同之处在于,这里我们有两个不同的数组,一个用于索引,一个用于值,而不是多列行

这样做的好处是不必实现排序算法,只需使用JDK中本机实现的TimSort即可。这是一个Junit实现

public class SortTest {
    Integer points[][] = {
        { 12, 13, 10, 0, 0, 0 },
        { 1, 2, 3, 4, 5, 6 }, 
    };

    private Integer[] sort(Integer tab[][]) {
        IndexComparator<Integer> comparator = new IndexComparator<>(tab[0]);
        List<Integer> indexList = (List<Integer>) new ArrayList<>(Arrays.asList(tab[1]));
        Collections.sort(indexList, comparator);
        Integer[] result = new Integer[indexList.size()];
        return indexList.toArray(result);
    }

    private static class IndexComparator<T extends Comparable> implements Comparator<Integer> {
        Integer[] values;

        public IndexComparator(Integer[] values) {
            this.values = values;
        }

        @Override
        public int compare(Integer t, Integer t1) {
            return values[t1-1] - values[t-1];
        }
    }

    @Test
    public void test() {
        Integer[] result = sort(points);
        assertEquals(new Integer[]{2,1,3,4, 5, 6}, result);
        Integer[] values = new Integer[result.length];
        for (int i=0; i<values.length; i++) {
            values[i] = points[0][result[i] - 1];
        }
        assertEquals(new Integer[]{13,12,10,0,0,0}, values);
    }
}

将每行视为单个数组。根据你对第一行的排序方式对第二行进行排序。@FelixMarcus事实上我不得不担心,我不应该删除它。白痴时刻。还有,yeesh。你应该实现你自己的排序方法吗?@Lonenebula不,这和我使用的方法是一样的。我只是在为并行排序而挣扎。我能问一下关于println的问题吗。当我运行它时,我得到:[12,0],[13,1]。难道不应该打印整个数组吗?您是否完全运行了我发布的代码?”我们得到:[13,12,10,0,0,0][2,1,3,4,5,6]如果数组像:{0,0,0,12,13,10},{1,2,3,4,5,6}我想结果应该是:{0,0,12,13,10,0},{1,2,4,5,6,3}
Arrays.sort(points, new Comparator<int[]>() {
    @Override
    public int compare(int[] o1, int[] o2) {
        return o2[0] - o1[0];
    }
});
public class SortTest {
    Integer points[][] = {
        { 12, 13, 10, 0, 0, 0 },
        { 1, 2, 3, 4, 5, 6 }, 
    };

    private Integer[] sort(Integer tab[][]) {
        IndexComparator<Integer> comparator = new IndexComparator<>(tab[0]);
        List<Integer> indexList = (List<Integer>) new ArrayList<>(Arrays.asList(tab[1]));
        Collections.sort(indexList, comparator);
        Integer[] result = new Integer[indexList.size()];
        return indexList.toArray(result);
    }

    private static class IndexComparator<T extends Comparable> implements Comparator<Integer> {
        Integer[] values;

        public IndexComparator(Integer[] values) {
            this.values = values;
        }

        @Override
        public int compare(Integer t, Integer t1) {
            return values[t1-1] - values[t-1];
        }
    }

    @Test
    public void test() {
        Integer[] result = sort(points);
        assertEquals(new Integer[]{2,1,3,4, 5, 6}, result);
        Integer[] values = new Integer[result.length];
        for (int i=0; i<values.length; i++) {
            values[i] = points[0][result[i] - 1];
        }
        assertEquals(new Integer[]{13,12,10,0,0,0}, values);
    }
}