Java 对ArrayList进行排序,但保持原始索引的顺序
有两个int数组和一个名为costs和shipping的数组列表。我想要一个总价格从最小到最大的ArrayList(例如成本[0]+运费[0]),但要对两个int数组重新排序以匹配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
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]));
}
}