如果存在重复,如何相对于另一个数组对数组进行排序



如果有唯一值,我可以相对于另一个数组对一个数组进行排序。但由于我正在尝试对以下给定的数组进行排序:

initial fuel[]={1,9,9,2,9,9};
initial cost[]={2,6,5,4,3,1};

我想对燃料阵列进行排序,然后又想对成本阵列进行排序
我想要下面给出的输出:

final fuel[]={1,2,9,9,9,9};
final cost[]={2,4,6,5,3,1};

以下是我的代码:

public static void sort(List<Integer> c, List<Integer> f) {
List<Integer> cc = new ArrayList<>(c);
Collections.sort(c);
List<Integer> al = new ArrayList<>();
int i = 0;
while (i < c.size()) {
int temp = c.get(i);
int index = cc.indexOf(temp);
al.add(f.get(index));
cc.remove(index);
f.remove(index);
i++;
}
for (int value : c)
System.out.print(value + " ");
System.out.println();
for (int value : al)
System.out.print(value + " ");
}

如何使用comparator以这种方式进行排序?同样如何使用流api?

如果您总是想将给定的燃料价值与成本相关联,那么我建议您创建一个类来保存它们。这将允许正确排序,同时将两个值保持在一起。

int[] fuel = { 1, 9, 9, 2, 9, 9 };
int[] cost = { 2, 6, 5, 4, 3, 1 };

这将创建类,并根据燃料值对其进行排序,然后将其放入列表中。

List<FuelInfo> fuelInfo =
// generate array indices
IntStream.range(0, fuel.length)

// create the objects 
.mapToObj(i -> new FuelInfo(fuel[i], cost[i]))
// sort them based on fuel value 
.sorted(Comparator.comparing(FuelInfo::getFuel))
// put them in a list.
.collect(Collectors.toList());

fuelInfo.forEach(System.out::println)

打印

[1, 2]
[2, 4]
[9, 6]
[9, 5]
[9, 3]
[9, 1]

您可以将单个值复制回如下列表:

List<Integer> fuelList = fuelInfo.stream()
.map(FuelInfo::getFuel).collect(Collectors.toList());
List<Integer> costList = fuelInfo.stream()
.map(FuelInfo::getCost).collect(Collectors.toList());

如果您想保持重复项的默认顺序,那么这将起作用,因为Java中的排序是稳定的(在比较等于值时保持插入顺序(。这是通过基于燃料阵列的值对索引进行排序,然后使用排序后的索引以正确排序的顺序构建成本列表来实现的。

Comparator<Integer> comp = (a,b)->Integer.compare(fuel[a],fuel[b]);
Comparator<Integer> comp =
(a, b) -> Integer.compare(fuel[a], fuel[b]);
List<Integer> sortedFuel = Arrays.stream(fuel).sorted()
.boxed().collect(Collectors.toList());
List<Integer> sortedCost = IntStream.range(0, fuel.length)
.boxed().sorted(comp).map(a -> cost[a])
.collect(Collectors.toList());
System.out.println(sortedFuel);
System.out.println(sortedCost);

打印

[1, 2, 9, 9, 9, 9]
[2, 4, 6, 5, 3, 1]

FuelInfo类


class FuelInfo{
private int fuelAmt;
private int cost;
public FuelInfo(int fuel, int cost) {
this.fuelAmt = fuel;
this.cost = cost;
}
public int getFuel() {
return fuelAmt;
}
public int getCost() {
return cost;
}
public String toString() {
return String.format("[%s, %s]", fuelAmt, cost);
}
}

使用以下内容:

Integer[] fuel = { 1, 9, 9, 2, 9, 9 };
Integer[] cost = { 2, 6, 5, 4, 3, 1 };
// Map each fuel number to a list of costs, keeps in order
// meaning that 9 will point to [6, 5, 3, 1] which is what
// we want.
Map<Integer, List<Integer>> map = new HashMap<>();
for (int i = 0; i < fuel.length; i++) {
if (!map.containsKey(fuel[i])) map.put(fuel[i], new ArrayList<>());
map.get(fuel[i]).add(cost[i]);
}
List<Integer> sortedFuel = Arrays.asList(fuel);
Collections.sort(sortedFuel);
List<Integer> rearrangedCost = new ArrayList<>();
for (int val : sortedFuel) {
// Get the first value of the mapping, which is the first that
// appears in cost
rearrangedCost.add(map.get(val).get(0));
map.get(val).remove(0);
}
System.out.println("final fuel = " + sortedFuel);
System.out.println("final fuel = " + rearrangedCost);

输出:

final fuel = [1, 2, 9, 9, 9, 9]
final fuel = [2, 4, 6, 5, 3, 1]

希望这就是你想要的!

假设这两个数组的长度相同,您可以创建包含这些数组中元素对的映射条目列表,并首先按然后按value对该列表进行排序,或者您可以仅按1键对其进行排序,按插入顺序排序:

Integer[] fuel = {1, 9, 9, 2, 9, 9, 2};
Integer[] cost = {2, 6, 5, 4, 3, 1, 5};
List<Map.Entry<Integer, Integer>> entryList = IntStream.range(0, fuel.length)
// create a Map with one entry 'fuel-cost'
.mapToObj(i -> Map.of(fuel[i], cost[i]))
// flatten all entries into one stream
.flatMap(map -> map.entrySet().stream())
// sorting entries
.sorted(Comparator
// first by key - fuel - in ascending order
.comparing((Map.Entry<Integer, Integer> entry) -> entry.getKey())
// then by value - cost - in descending order, or without a
// second comparator, duplicates are sorted in insertion order
.thenComparing(Map.Entry::getValue, Comparator.reverseOrder()))
// return sorted list of entries
.collect(Collectors.toList());
System.out.println(entryList); // [1=2, 2=5, 2=4, 9=6, 9=5, 9=3, 9=1]
// if you want to replace the contents of the arrays
IntStream.range(0, entryList.size()).forEach(i -> {
fuel[i] = entryList.get(i).getKey();
cost[i] = entryList.get(i).getValue();
});
System.out.println(Arrays.toString(fuel)); // [1, 2, 2, 9, 9, 9, 9]
System.out.println(Arrays.toString(cost)); // [2, 5, 4, 6, 5, 3, 1]

另请参阅:收集基于多个字段的ID列表

相关内容

最新更新