找到未排序数组的顺序

时间:2017-05-08 17:36:35

标签: java arrays sorting

我有一个数组long[100] arr;,我想"排名"数组中的元素。意思是我想知道哪一个是最小的,哪一个是最小的,依此类推。

我知道我可以制作副本,对其进行排序,然后在未排序的数组中找到排序数组中的每个元素,但这似乎是执行此简单任务的一种非常麻烦的方式。

Java中是否有一个函数可以为您提供未排序数组的顺序? 我知道在R中有两个不同的函数,sort()order(),每个任务一个。

//example
long[] arr = {1983, 321, 63, 832, 455, 1466, 788, 25425, 1839}
Arrays.sort(arr); // arr = {63, 321, 455, 788, 832, 1466, 1839, 1983, 25425}
// I'm looking for a function that will give me this-
int[] order = foo(arr); // order = {7, 0, 8, 5, 3, 6, 4, 1, 2}

3 个答案:

答案 0 :(得分:6)

可以创建一个索引数组,然后根据long数组中的值对其进行排序:

import java.util.*;

class Example {
    static Integer[] getSortedIndexes(final long[] arr) {
        Integer[] indexes = new Integer[arr.length];
        for (int n = 0; n < indexes.length; ++n) {
            indexes[n] = n;
        }
        Arrays.sort(indexes, (left, right) -> Long.compare(arr[right], arr[left]));
        return indexes;
    }
    public static void main(String[] args) {
        long[] arr = {1983, 321, 63, 832, 455, 1466, 788, 25425, 1839};
        Integer[] indexes = getSortedIndexes(arr);
        System.out.println(Arrays.toString(indexes));
    }
}

使用您的示例输入,产生:

[7, 0, 8, 5, 3, 6, 4, 1, 2]

Live on IDEone

我不能说它很漂亮:-),但是:

  • 您不必查找已排序结果的索引。
  • 它正确处理原始数组中的两个等效值。
  • 它没有创建一堆中间对象(虽然遗憾的是它确实涉及Integer个实例,而不仅仅是int s。。
  • 很简单。

如果您想要int[]结果,则必须在结尾添加一个传递,可以是简单的for循环,也可以是Stream#mapToInt(更高级但更重)。

或者,如果你想在溪流上进行全面的屠宰,请SkinnyJ points out

static int[] getSortedIndexes(final long[] arr) {
    return IntStream.range(0, arr.length).boxed().sorted((right, left) -> Long.compare(arr[left], arr[right])).mapToInt(i->i).toArray();
}

答案 1 :(得分:4)

我使用TreeMap,反转键和索引。 TreeMap按提供的Comparator对迭代进行排序,因此使用Comparator.reverseOrder来获得最大到最小的排序:

int[] order(long[] arr) {
    Map<Long, Integer> map = new TreeMap<>(Comparator.reverseOrder());
    for(int i = 0; i < arr.length; i++) {
        map.put(arr[i], i);
    }
    return map.values().stream().mapToInt(i->i).toArray();
}

这是使用流的单行:

int[] order(long[] arr) {
    IntStream.range(0, arr.length)
      .collect(() -> new TreeMap<Long, Integer>(Comparator.reverseOrder()),
               (map, i) -> map.put(arr[i], i), 
               Map::putAll)
      .values().stream().mapToInt(i->i).toArray();
}

答案 2 :(得分:1)

您也可以在一个Stream管道中执行此操作。

public static int[] order(long... ls) {
  //If ls == null then throw a NullPointerException
  Objects.requireNonNull(ls);
  //Generate a IntStream in range [0, ls.length[
  return IntStream.range(0, ls.length)
      //convert int to Integer
      .boxed()
      //Sort the numbers according to the value in the array
      .sorted(
         //Convenient function to create a Comparator.
         //Same as: (left, right) -> Long.compare(ls[right], ls[left])
         Comparator.comparingLong((Integer i) -> ls[i]).reversed()
      //Since values are boxed (i.e. Integer) convert back to int
      ).mapToInt(Integer::intValue)
      //Create the int array (i.e. int[])
      .toArray();
}