Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/346.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 对ArrayList进行排序,但保持原始索引的顺序_Java_Arrays_Sorting_Arraylist - Fatal编程技术网

Java 对ArrayList进行排序,但保持原始索引的顺序

Java 对ArrayList进行排序,但保持原始索引的顺序,java,arrays,sorting,arraylist,Java,Arrays,Sorting,Arraylist,有两个int数组和一个名为costs和shipping的数组列表。我想要一个总价格从最小到最大的ArrayList(例如成本[0]+运费[0]),但要对两个int数组重新排序以匹配ArrayList: Scanner scan = new Scanner(System.in); int n = scan.nextInt(); int[] costs = new int[n]; int[] shipping = new int[n]; ArrayList<Integer> totalC

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

Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int[] costs = new int[n];
int[] shipping = new int[n];
ArrayList<Integer> totalCosts = new ArrayList<>();
Scanner scan=新的扫描仪(System.in);
int n=scan.nextInt();
int[]成本=新int[n];
int[]shipping=新int[n];
ArrayList totalCosts=新的ArrayList();
例如,假设成本为[1,5,2,3],运输成本为[2,3,2,4],那么总成本为{3,8,4,7},排序为{3,4,7,8}。我希望对成本和配送进行重新排序,使其与总计相对应,从而使成本为[1,2,3,5],配送为[2,2,4,3]。

公共列表分拣费(int[]成本,int[]配送){
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;
}
列表结果=新建ArrayList(); TreeMap map=newtreemap(); int length=cost.length; int[]origCost=新int[长度]; int[]origShipping=新int[长度]; for(int i=0;i
我用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

这里有一个不使用地图的解决方案。相反,我们有一个定制的比较器,它使用成本和运输的总和对阵列位置进行排序。然后,我们创建新数组,并从旧数组中排序的位置中选取值

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

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

  • 创建一个
    ,将总计和索引存储在
    int[]
    数组中

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

  • 有意使用
    peek
    AtomicInteger
    来重新排序输入
    成本
    发货
    数组
    注:然而,这可能被认为是一种“滥用”,由于数据流之外的数据更新的副作用而加剧

  • 构建并返回总计数组

  • publicstaticint[]getTotals(int[]costs,int[]ships){
    断言costs.length==ships.length;
    int[]copyCosts=Arrays.copyOf(costs,costs.length);
    int[]copychips=Arrays.copyOf(ships,ships.length);
    AtomicInteger ix=新的AtomicInteger(0);
    return IntStream.range(0,costs.length)
    .mapToObj(i->newint[]{costs[i]+ships[i],i})
    .分类(比较)。
    比较(p->p[0])
    .然后比较(p->p[1])
    )//获取排序流
    .peek(p->{
    成本[ix.get()]=copyCosts[p[1]];
    ships[ix.getAndIncrement()]=复制[p[1]];
    })
    .mapToInt(p->p[0])
    .toArray();
    }
    
    您想要这样做,您尝试过实现什么?这是非常困难的,因为您需要根据排序移动列表元素的方式来移动数组元素。创建一个包含成本、运费和总价的新类更容易。然后列一个清单,并对其进行排序。一般来说,有。我将创建一个
    List
    ,其中Order类有两个字段,cost和shipping,以及一个方法
    getTotal
    ,将它们相加。然后,排序变得很简单,因为数据在逻辑上被分组到对象中,所以索引会自动维护。如果你真的需要使用HashMap,你可以将其重新划分成新的数组,在这里使用HashMap可能会更好,然后在你的映射上调用sort,因为默认的排序是稳定的,所以不应该有任何问题!上述措施应该有效。该映射是一个树形映射,键是总价,值是长度为2的数组列表。必须使用列表,因为我们可能不止一次拥有相同的总价。其余的我相信是可以自我解释的。既然你要用
    comparingit
    来使用Java8,那么你最好使用
    int[]totals=IntStream.range(0,n)
    int[]newCosts=IntStream.of(totals).map(I->costs[I]).toArray()好的观点。我同意这是一个更好的选择,尽管如果您不熟悉streams,可能更难理解。
    
    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]));
        }
    }