【问题标题】:Sorting two parallel arrays对两个并行数组进行排序
【发布时间】:2016-07-26 05:29:28
【问题描述】:

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

例如:

  • 市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};

大问题!

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

【问题讨论】:

  • 因为它们是相关信息,所以将这两个信息存储在一个城市对象上可能是个好主意。

标签: java arrays sorting


【解决方案1】:

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

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());

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

【讨论】:

  • City 类甚至可以实现Comparable&lt;City&gt; 作为替代方案。这样,您就可以调用Collections.sort,只使用cities 的集合。
  • 此外,在处理排序和集合时,您的对象也应该覆盖 equals()hashCode() 方法。这将使每个对象真正独一无二。
  • @Mr.Polywhirl 是的。因为我认为这不是 City 的“自然”排序,所以我更喜欢 Comparator 方式。
  • @Mr.Polywhirl 将有多种城市排序方式。我不确定按人口排序是否比按 id 排序更自然。这使得使用 Comparator 进行特定排序是一个很好的计划。我会称它为 CityPopulationComparator。
  • @AliSeyedi:如果两个城市的人口相等,ids 的顺序重要吗?
【解决方案2】:

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

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&lt;IntBuffer&gt;List&lt;List&lt;Integer&gt;&gt;,它将被修复。

【讨论】:

    【解决方案3】:

    如果您的城市 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());
    

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

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

        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]
        

        另见:How do I sort two arrays in relation to each other?

        【讨论】:

          【解决方案6】:
          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);
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-04-17
            • 2011-07-27
            • 1970-01-01
            • 2011-12-26
            • 1970-01-01
            • 2011-04-23
            相关资源
            最近更新 更多