[英]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.