2010-11-29 87 views
3

我有什麼似乎是一個簡單的問題,但到目前爲止我無法弄清楚。排序兩個數組(值,鍵),然後排序鍵

說我有兩個數組:

int[] values = {10,20,20,10,30}; 
int[] keys = {1,2,3,4,5}; 

Array.Sort(values,keys); 

然後陣列是這樣的:

values = {10,10,20,20,30}; 
keys = {4,1,2,3,5}; 

現在,我想要做的就是讓這個鍵在也會分類第二個優先級,所以鍵陣看起來像這樣:

keys = {1,4,2,3,5}; 

注意1和4值被切換,並且o f值數組沒有改變。

回答

6

如果「就地分揀」是不是絕對必要的你,我建議使用OrderBy

var sortedPairs = values.Select((x, i) => new { Value = x, Key = keys[i] }) 
         .OrderBy(x => x.Value) 
         .ThenBy(x => x.Key) 
         .ToArray(); // this avoids sorting 2 times... 
int[] sortedValues = sortedPairs.Select(x => x.Value).ToArray(); 
int[] sortedKeys = sortedPairs.Select(x => x.Key).ToArray(); 

// Result: 
// sortedValues = {10,10,20,20,30}; 
// sortedKeys = {1,4,2,3,5}; 
+0

1 LINQ救援 – bitxwise 2010-11-29 22:55:32

1

通常,平行陣列會皺眉。數據很容易失去同步。我會建議使用地圖/字典數據類型,或將鍵和值存儲在單個對象中,然後使用所述對象的數組。

編輯:重新閱讀你的問題後,我不認爲字典是你想要的數據類型,根據你的需要排序值。不過,我仍然會建議擁有一個包含鍵和值的對象。然後,您可以按值排序,並確信它們的鍵不會失去同步。

1

Array.Sort(值,鍵)將使用默認比較器對值和鍵進行排序。您需要編寫一個自定義比較器來執行您所描述的內容,並將您的比較器傳遞給Array.Sort方法。

0

我想接受的答案是偉大的。可以使用匿名類型,如該答案中所示,或者聲明一個命名類型以在排序時保存數據。

更好的是,聲明一個指定類型來保存數據全部的時間。並行數組通常不是一個好主意。在性能或互操作性原因需要使用它們的情況下,它們應該被避免。

這就是說,爲了完整性,我認爲指出數組可以被「按代理」排序是有用的。即創建一個新的數組,它只是原始數組的索引,並排序數組。索引數組排序後,可以使用該數組直接訪問原始數據,也可以使用該數組將原始數據複製到新的排序數組中。

例如:

static void Main(string[] args) 
{ 
    int[] values = { 10, 20, 20, 10, 30 }; 
    int[] keys = { 1, 2, 3, 4, 5 }; 

    int[] indexes = Enumerable.Range(0, values.Length).ToArray(); 

    Array.Sort(indexes, (i1, i2) => Compare(i1, i2, values, keys)); 

    // Use the index array directly to access the original data 
    for (int i = 0; i < values.Length; i++) 
    { 
     Console.WriteLine("{0}: {1}", values[indexes[i]], keys[indexes[i]]); 
    } 

    Console.WriteLine(); 

    // Or go ahead and copy the old data into new arrays using the new order 
    values = OrderArray(values, indexes); 
    keys = OrderArray(keys, indexes); 

    for (int i = 0; i < values.Length; i++) 
    { 
     Console.WriteLine("{0}: {1}", values[i], keys[i]); 
    } 
} 

private static int Compare(int i1, int i2, int[] values, int[] keys) 
{ 
    int result = values[i1].CompareTo(values[i2]); 

    if (result == 0) 
    { 
     result = keys[i1].CompareTo(keys[i2]); 
    } 

    return result; 
} 

private static int[] OrderArray(int[] values, int[] indexes) 
{ 
    int[] result = new int[values.Length]; 

    for (int i = 0; i < values.Length; i++) 
    { 
     result[i] = values[indexes[i]]; 
    } 

    return result; 
}