对 ArrayList 排序但保持原始索引的顺序

时间:2021-01-10 21:47:56

标签: java arrays sorting arraylist

有两个 int 数组和一个名为 cost 和 shipping 的数组列表。我想要一个总价从最小到最大的 ArrayList(例如成本 [0] + 运输 [0]),但重新排序两个 int 数组以匹配 ArrayList:

find "A notional thesis title" in field "Title"

例如,假设成本是 [1, 5, 2, 3] 并且运费是 [2, 3, 2, 4],所以总成本将为 {3, 8, 4, 7} 并且将被排序为{3, 4, 7, 8}。我希望对成本和运费进行重新排序,使它们与总数相对应,因此成本为 [1, 2, 3, 5],运费为 [2, 2, 4, 3]。

4 个答案:

答案 0 :(得分:1)

这是一个不使用地图的解决方案。相反,我们有一个自定义的 Comparator,它使用成本和运费的总和来对数组位置进行排序。然后我们创建新数组并从旧数组的排序位置中选取值。

public static void main(String[] args) {
    int n = 4;
    int[] costs = {1, 5, 2, 3};
    int[] shipping = {2, 3, 2, 4};
    Integer[] totals = new Integer[n];
    for(int i = 0; i < n; ++i) {
        totals[i] = i;
    }

    Arrays.sort(totals, Comparator.comparingInt(k -> (costs[k] + shipping[k])));

    int[] newCosts = new int[n];
    int[] newShipping = new int[n];
    for(int i = 0; i < n; ++i) {
        newCosts[i] = costs[totals[i]];
        newShipping[i] = shipping[totals[i]];
    }

    for(int i = 0; i < n; ++i){
        System.out.println((i + 1) + ": Cost=" + newCosts[i] + ", Shipping=" + newShipping[i] + ", Total=" + (newCosts[i] + newShipping[i]));
    }
}

说明

totals 数组包含从 0 到 n 的索引列表(示例中为 4)。 Arrays.sort() 使用 Comparator 对索引进行排序,在给定索引的情况下,它会提取该位置的总数。 totals 数组排序后,将按顺序列出成本和运费总和的索引。

之后,我们可以使用排序索引创建新的成本和运输数组。

编辑

根据评论中的 ttzn 建议,您可以将代码压缩为:

public static void main(String[] args) {
    int n = 4;
    int[] costs = {1, 5, 2, 3};
    int[] shipping = {2, 3, 2, 4};

    int[] totals = IntStream.range(0, n).boxed().sorted(Comparator.comparingInt(k -> (costs[(int)k] + shipping[(int)k]))).mapToInt(Integer::intValue).toArray();

    int[] newCosts = IntStream.of(totals).map(i -> costs[i]).toArray();
    int[] newShipping = IntStream.of(totals).map(i -> shipping[i]).toArray();

    for (int i = 0; i < n; ++i) {
        System.out.println((i + 1) + ": Cost=" + newCosts[i] + ", Shipping=" + newShipping[i] + ", Total=" + (newCosts[i] + newShipping[i]));
    }
}

答案 1 :(得分:1)

这是一个无需构建地图的基于流的解决方案。

  1. 构建了一个 Stream<int[]>,在 int[] 数组中存储总数和索引,

  2. 使用自定义比较器对这些数组进行排序(首先按总数,然后按索引)

  3. 有意使用 peekAtomicInteger 重新排序输入 costsships 数组
    注意:然而,这可能被认为是“滥用”,因为数据流外的副作用更新

  4. 构建并返回总数数组。

public static int[] getTotals(int[] costs, int[] ships) {
    assert costs.length == ships.length;
    int[] copyCosts = Arrays.copyOf(costs, costs.length);
    int[] copyShips = Arrays.copyOf(ships, ships.length);
    
    AtomicInteger ix = new AtomicInteger(0);
    
    return IntStream.range(0, costs.length)
                    .mapToObj(i -> new int[]{ costs[i] + ships[i], i })
                    .sorted(Comparator.<int[]>
                        comparingInt(p -> p[0])
                        .thenComparingInt(p -> p[1])
                    ) // get sorted Stream<int[]>
                    .peek(p -> {
                        costs[ix.get()] = copyCosts[p[1]];
                        ships[ix.getAndIncrement()] = copyShips[p[1]];
                    })
                    .mapToInt(p -> p[0])
                    .toArray();
}

答案 2 :(得分:0)

public List<Integer> sortPrices(int[] cost, int[] shipping) {
    List<Integer> result = new ArrayList<>();
    TreeMap<Integer, List<int[]>> map = new TreeMap<>();
    int length = cost.length;
    int[] origCost = new int[length];
    int[] origShipping = new int[length];
    for (int i = 0; i < length; i++) {
        int price = cost[i] + shipping[i];
        int[] arr = {i, i};
        map.putIfAbsent(price, new ArrayList<>());
        map.get(price).add(arr);
        origCost[i] = cost[i];
        origShipping[i] = shipping[i];
    }
    int j = 0;
    for (int price : map.keySet()) {
        for (int[] arr : map.get(price)) {
            int ci = arr[0];
            int si = arr[1];
            cost[j] = origCost[ci];
            shipping[j] = origShipping[si];
            j++;
            result.add(price);
        }
    }
    return result;
}

答案 3 :(得分:0)

我是用python解决的

只要了解循环逻辑,你就可以做到。

for i in range(len(total)):
  for j in range(len(total)):
    if sorted_total[i]==total[j]:
        new_costs[i]=costs[j]
        new_shipping[i]=shipping[j]
        print("i ",i)
        print("j ",j)
        break