简体   繁体   English

Java:使用indexOf方法基于另一个数组对数组进行排序

[英]Java: Sorting an array based on another array with indexOf method

I want to iterate through two arrays(A, B) based on the sorted order of another array(indexes), which is 10, 34, 32, 21 in this case. 我想基于另一个数组(索引)的排序顺序迭代两个数组(A,B),在这种情况下是10,34,32,21。

String[] A: a, b, c, d
String[] B: e, f, g, h
int[] indexes: 10, 34, 32, 21

Apology for the bad example here. 在这里为坏榜样道歉。 I have updated the indexes array to clear the confusion. 我更新了索引数组以清除混淆。

Expected Input and Output 预期的输入和输出

The input are the three arrays. 输入是三个数组。 I wanted to iterate through A, B using the sorted of the indexes array. 我想使用索引数组的排序迭代A,B。 ie I want to find a way to iterate A using the order (a, d, c, b) and iterate B using the order (e, h, g, f) 即我想找到一种方法来使用顺序(a,d,c,b)迭代A并使用顺序(e,h,g,f)迭代B

My approach: 我的方法:

I solved the problem with a solution that I believe is identical to another approach. 我用一种我认为与另一种方法相同的解决方案解决了这个问题。 However, the second approach does not work. 但是,第二种方法不起作用 I would appreciate if someone can explain why it does not work as I think it would give me a better understanding of how Collections.sort works in java. 如果有人可以解释为什么它不起作用我会很感激,因为我认为这会让我更好地理解Collections.sort在java中的工作原理。

List<Integer> indexOrder = new ArrayList<>(indexes.length);

for (int i = 0; i < indexes.length; i++) {
    indexOrder.add(i);
}

Collections.sort(indexOrder, Comparator.comparing((Integer s) -> indexes[s]));

Inspired by this thread , I created an ArrayList (prefer AList not array) with value (1, 2, 3...indexes.length) and then sort it using a comparator with ref. 这个线程的启发,我创建了一个ArrayList(更喜欢AList not array),其值为(1,2,3 ... indices.length),然后使用带有ref的比较器对其进行排序。 to indexes. 索引。 The codes above work as expected. 上述代码按预期工作。

However, if I change the indexes[s] at the end of the last line to indexes[indexOrder.indexOf(s)] . 但是,如果我将最后一行末尾的索引[s]更改为索引[indexOrder.indexOf(s)] The sorting will give a wrong result. 排序会产生错误的结果。 Why is indexOf(s) giving a different result than s if the ArrayList's index is the same as its value. 如果ArrayList的索引与其值相同,为什么indexOf(s)给出的结果与s不同。

Collections.sort(indexOrder, Comparator.comparing((Integer s) -> indexes[indexOrder.indexOf(s)]));

It seems you expect indexOrder.indexOf(s) to always be equal to s (since your List was initialized to [0, 1, 2, 3] , where the index of s is s ). 看起来你期望indexOrder.indexOf(s)始终等于s (因为你的List被初始化为[0, 1, 2, 3] ,其中s的索引是s )。

While this is true in your original indexOrder List , this may no longer true when Collections.sort starts swapping elements of your List . 虽然在原始indexOrder List也是如此,但当Collections.sort开始交换List元素时,这可能不再成立。

In order not to rely on the ordering of indexOrder while you are sorting it, you can create a copy of that List : 为了在排序时不依赖indexOrder的顺序,您可以创建该List的副本:

List<Integer> copy = new ArrayList<>(indexOrder);
Collections.sort(indexOrder, Comparator.comparing((Integer s) -> indexes[copy.indexOf(s)]));

Since the maximum value stored in indexes won't exceed 1000 i feel like an implementation of this sorting algorithm (which is a variant of the counting sort) will be the best choice. 由于存储在索引中的最大值不会超过1000,我觉得这种排序算法的实现(这是计数排序的变体)将是最佳选择。

final String[] A = { "a", "b", "c", "d" };
final String[] B = { "e", "f", "g", "h" };
final int[] indexes =  { 10, 34, 32, 21 };

// find out the max value in the array.
// The loop can be skipped with maxIndexValue = 1000; but i would most likely save some memory using the loop.
// Can also be replaced with : IntStream.of(indexes).max().getAsInt(), with such a small set of data it won't hurt performance that bad
int maxIndexValue = 0;
for (int indexValue: indexes) {
    if (maxIndexValue < indexValue) {
        maxIndexValue = indexValue;
    }
}
maxIndexValue += 1;

final String[] indexSortedA = new String[maxIndexValue];
final String[] indexSortedB = new String[maxIndexValue];
System.out.println(maxIndexValue);
// each value of A (and B) will be put at indexes position, it will result in a appropriately sorted arrays but with a lot of whitespace.
for (int i = 0; i < indexes.length; ++i) {
    indexSortedA[indexes[i]] = A[i];
    indexSortedB[indexes[i]] = B[i];
}

// Create final arrays by filtering empty values
final String[] sortedA = Arrays.stream(indexSortedA).filter(v -> v != null && !"".equals(v)).toArray(String[]::new);
final String[] sortedB = Arrays.stream(indexSortedB).filter(v -> v != null && !"".equals(v)).toArray(String[]::new);

Complexity of this algorithm will be : O(n) + O(1000) + O(2n). 该算法的复杂度为:O(n)+ O(1000)+ O(2n)。 It will be better nthan any Collection.sort() but it cost a bit more memory. 它会比任何Collection.sort()更好,但它会花费更多的内存。

I tried to ran both the code and I get the same result in both the cases. 我试图运行这两个代码,我在两种情况下得到相同的结果。

Case 1 : 情况1 :

public static void main(String[] args) {
    String[] A = { "a", "b", "c", "d" };
    String[] B = { "e", "f", "g", "h" };
    int[] indexes = { 0, 4, 2, 1 };

    List<Integer> indexOrder = new ArrayList<>(indexes.length);

    for (int i = 0; i < indexes.length; i++) {
        indexOrder.add(i);
        System.out.println(i);
    }

    //Collections.sort(indexOrder, Comparator.comparing((Integer s) -> indexes[s]));
    Collections.sort(indexOrder, Comparator.comparing((Integer s) -> indexes[indexOrder.indexOf(s)]));

    System.out.println(indexOrder.toString());
}

Ouput : 0 1 2 3 输出:0 1 2 3

[0, 3, 2, 1] [0,3,2,1]

Case 2: 案例2:

public static void main(String[] args) {
    String[] A = { "a", "b", "c", "d" };
    String[] B = { "e", "f", "g", "h" };
    int[] indexes = { 0, 4, 2, 1 };

    List<Integer> indexOrder = new ArrayList<>(indexes.length);

    for (int i = 0; i < indexes.length; i++) {
        indexOrder.add(i);
        System.out.println(i);
    }

    Collections.sort(indexOrder, Comparator.comparing((Integer s) -> indexes[s]));
    //Collections.sort(indexOrder, Comparator.comparing((Integer s) -> indexes[indexOrder.indexOf(s)]));

    System.out.println(indexOrder.toString());
}

output : 0 1 2 3 输出:0 1 2 3

[0, 3, 2, 1] [0,3,2,1]

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

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