[英]Is there any simple way to preserve original indices after sorting array without using Comparator?
我實現了一個數組,其中我采用了一個零索引的數組。 考慮下面的數組:
Array : X S T U A C D B F H
Index : 0 1 2 3 4 5 6 7 8 9
After sorting this array :
Array : A B C D F H S T U X
Index : 0 1 2 3 4 5 6 7 8 9
Original indices : 4 7 5 6 8 9 1 2 3 0
之前的 A 位於索引 4,但在排序數組中,它位於索引 0,其他值也相同。 程序預期的輸出表示為原始索引。 我想在排序后打印它們的原始索引,而不是打印排序數組中的元素。
雖然這段代碼工作正常,但我想知道是否有任何其他簡單的技術可以用來在不使用 Comparator 的情況下保留原始數組索引。 這里的想法是保留索引,因此我使用 Comparator :
在這個 Comparator 中,我保留了要排序的實際數組。 此外,如果您注意到,compare 方法會根據提供給它的索引來比較實際數組的值。 這里的關鍵是提供索引而不是要排序的實際值。
S是要排序的字符數組,indexArray是一個輔助數組。 在排序之前,索引數組將包含序列中的數字 0 – 要排序的數組的長度。 當我在索引數組上調用 Arrays.sort 方法時,它將兩個索引傳遞給 compare 方法並比較存儲在這些索引處的值。
```public class ArrayIndexComparator implements Comparator<Integer>
{
private final Character[] A;
public ArrayIndexComparator(Character[] arr)
{
this.A = arr;
}
public int compare(Integer o1, Integer o2)
{
return A[o1].compareTo(A[o2]);
}
}```
```public static void main(String[] args)
{
Character[] S = new Character[]{'X','S','T','U','A','C','D','B','F','H'};
Integer[] indexArray = new Integer[S.length];
IntStream.range(0, S.length).forEach(val -> indexArray[val] = val);
ArrayIndexComparator comp = new ArrayIndexComparator(S);
Arrays.sort(indexArray, comp);
System.out.println(Arrays.toString(indexArray));
}```
你可以這樣做。
String[] arr =
{ "X", "S", "T", "U", "A", "C", "D", "B", "F", "H" };
根據字符串對索引進行排序
int[] intArray = IntStream.range(0, arr.length).boxed()
.sorted(Comparator.comparing(i -> arr[i]))
.mapToInt(Integer::intValue).toArray();
System.out.println(Arrays.toString(intArray));
然后使用Arrays.setAll
構造排序后的字符數組。
String[] newArr = new String[arr.length];
Arrays.setAll(newArr,i->arr[intArray[i]]);
System.out.println(Arrays.toString(newArr));
印刷
[4, 7, 5, 6, 8, 9, 1, 2, 3, 0]
[A, B, C, D, F, H, S, T, U, X]
至少有幾種方法可以避免使用自定義Comparator
按索引而不是值進行排序,但它們並不簡單,我強烈建議不要使用它們 - 為了感興趣,我在這里介紹了主題。
順便說一句,使用Comparator
的 lambda 形式可以稍微簡化您的代碼:
Arrays.setAll(indexArray, i -> i);
Arrays.sort(indexArray, (a, b) -> S[a].compareTo(S[b]));
第一個想法是創建一個代理值,該值結合了原始Character
值及其索引,例如,將值乘以數組n
的長度並添加索引。 在對這個代理值進行排序后,您可以通過使用mod
n
來獲取索引來反轉包裝。
Character[] s = new Character[]{'X','S','T','U','A','C','D','B','F','H'};
int n = s.length;
Integer[] idx = new Integer[s.length];
for(int i=0; i<s.length; i++) idx[i] = s[i]*n + i;
System.out.println(Arrays.toString(idx));
Arrays.sort(idx);
System.out.println(Arrays.toString(idx));
for(int i=0; i<s.length; i++) idx[i] %= n;
System.out.println(Arrays.toString(idx));
輸出:
[880, 831, 842, 853, 654, 675, 686, 667, 708, 729]
[654, 667, 675, 686, 708, 729, 831, 842, 853, 880]
[4, 7, 5, 6, 8, 9, 1, 2, 3, 0]
這里明顯的問題是大數組和/或字符的溢出。
另一種選擇是使用映射來存儲字符的原始位置,並在對原始數組進行排序后執行查找。
Character[] s = new Character[]{'X','S','T','U','A','C','D','B','F','H'};
Map<Character,Integer> map = new HashMap<>();
for(int i=0; i<s.length; i++) map.put(s[i], i);
System.out.println(map);
Arrays.sort(s);
Integer[] idx = new Integer[s.length];
for(int i=0; i<s.length; i++) idx[i] = map.get(s[i]);
System.out.println(Arrays.toString(idx));
輸出:
{A=4, B=7, C=5, S=1, D=6, T=2, U=3, F=8, H=9, X=0}
[4, 7, 5, 6, 8, 9, 1, 2, 3, 0]
這里的問題是不允許重復。
您可以使用Comparator.comparing更輕松地定義您的Comparator 。
Comparator<Integer> comp = Comparator.comparing(i -> S[i]);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.