簡體   English   中英

有沒有什么簡單的方法可以在不使用 Comparator 的情況下對數組進行排序后保留原始索引?

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM