繁体   English   中英

排序两个并行 arrays

[英]Sorting two parallel arrays

我有两个arrays,一个存储城市的距离,另一个存储相应的人口。 如果城市的距离按升序排列,一切正常。 但是假设有人随机输入距离。 如何对城市数组进行排序,并确保各个城市的人口与其各自城市人口的索引处于同一索引中。

例如:

  • 城市 1 有人口 333
  • 城市 3 有人口 33333
  • 城市 5 有人口 33
int[] city = {1, 3, 5};
int[] pop  = {333, 33333, 33};

一切正常,因为城市数组已经排序。

但是当我输入:

int[] city = {3, 1, 5};
int[] pop  = {3333, 333, 33};

大问题!

我想对数组 city 进行排序,并确保 population 数组的所有元素与其各自城市的索引相同。

这样做的好方法是有一个城市类:

class City{
    private int id;
    private long population;

    //... getters, setters, etc
}

城市比较器类:

class CityPopulationComparator implements Comparator<City> {
    @Override
    public int compare(City c1, City c2) {
        return Long.compare(c1.getPopulation(), c2.getPopulation());
    }
}

以及城市的数组列表:

ArrayList<City> cities;

最后使用以下方法对其进行排序:

Collections.sort(cities, new CityPopulationComparator());

但是,如果您需要以这种方式拥有您的城市和人口,您可以自己编写一个排序方法(例如冒泡排序),并且每当您交换两个城市时,也交换相应的人口。

正确的解决方案是这样的 但是,如果你想要一个完全疯狂的黑客,你可以这样做:

public final class ParallelIntArrays extends AbstractList<int[]> {

    private final int[] array1;
    private final int[] array2;

    public ParallelIntArrays(int[] array1, int[] array2) {
        if (array1.length != array2.length)
            throw new IllegalArgumentException();
        this.array1 = array1;
        this.array2 = array2;
    }

    @Override
    public int[] get(int i) {
        return new int[] { array1[i], array2[i] };
    }

    @Override
    public int size() {
        return array1.length;
    }

    @Override
    public int[] set(int i, int[] a) {
        if (a.length != 2)
            throw new IllegalArgumentException();
        int[] b = get(i);
        array1[i] = a[0];
        array2[i] = a[1];
        return b;
    }
}

然后你可以这样做:

int[] city = {5,   1,  2,    4,   3   };
int[] pop =  {100, 30, 4000, 400, 5000};
new ParallelIntArrays(city, pop).sort(Comparator.comparingInt(arr -> arr[0]));
System.out.println(Arrays.toString(city));
System.out.println(Arrays.toString(pop));

请注意,如上所述, ParallelIntArrays不能作为List正常运行。 例如list.contains(list.get(0))会给出false 如果您将其List<IntBuffer>List<List<Integer>> ,它将被修复。

如果您的城市 ID 是唯一的:

int[] city = { 3,    1,   5};
int[] pop  = {3333, 333, 33};
Map<Integer, Integer> arr = new HashMap<>(city.length);
for (int i = 0; i < city.length; i++) {
    arr.put(city[i], pop[i]);
}
Arrays.sort(city);
for (int i = 0; i < city.length; i++) {
    pop[i] = arr.get(city[i]);
}

同样使用SortedMap

int[] city = { 3,    1,   5};
int[] pop  = {3333, 333, 33};
SortedMap<Integer, Integer> arr = new TreeMap<>();
for (int i = 0; i < city.length; i++) {
    arr.put(city[i], pop[i]);
}
System.out.println(arr.keySet());
System.out.println(arr.values());

“便宜”的方法是使用第三个数组,其中包含 0 到 n 表示其他数组的索引

但是,如果将它们分组在一个类中,您遇到的问题就会消失,这两种信息在逻辑上似乎是相关的。 然后你将实现 Comparable: https : //stackoverflow.com/a/18896422

public static void main(String[] args) {
    Integer[] bidAmount = {3000, 54000, 2000, 1000, 5600};
    String[] bidderName = {"Jenny", "Mike", "Alvin", "Berry", "John"};
    Map<Integer, String> stringTreeMap = new TreeMap<>();
    stringTreeMap.put(bidAmount[0], bidderName[0]);
    stringTreeMap.put(bidAmount[1], bidderName[1]);
    stringTreeMap.put(bidAmount[2], bidderName[2]);
    stringTreeMap.put(bidAmount[3], bidderName[3]);
    stringTreeMap.put(bidAmount[4], bidderName[4]);

    for (Map.Entry<Integer, String> entry : stringTreeMap.entrySet()) {
        Integer key = entry.getKey();
        String value = entry.getValue();

        System.out.println(key + " => " + value);
    }
}

您可以收集包含这两个数组的元素对的第三个数组并对其进行排序。 然后你可以迭代这个数组并替换前两个数组的元素:

int[] city = {3, 1, 5};
int[] pop = {333, 33333, 33};

int[][] sorted = IntStream.range(0, city.length)
        // Stream<int[]>
        .mapToObj(i -> new int[]{city[i], pop[i]})
        // sort by city
        .sorted(Comparator.comparing(arr -> arr[0]))
        .toArray(int[][]::new);

// replace the elements of the first two arrays
IntStream.range(0, sorted.length).forEach(i -> {
    city[i] = sorted[i][0];
    pop[i] = sorted[i][1];
});

System.out.println(Arrays.toString(city)); // [1, 3, 5]
System.out.println(Arrays.toString(pop)); // [33333, 333, 33]

另请参阅:如何对两个数组进行相互排序?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM