2010-11-29 31 views
3

シンプルな問題があるようですが、これまでのところ理解できません。2つの配列(値、キー)をソートしてから、キーをソートする

は、私は2つの配列を持っていると言う:

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の値が切り替えられ、 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

1

一般的に、パラレルアレイはぼんやりしています。データが同期しなくなることは非常に簡単です。私が示唆しているのは、マップ/ディクショナリデータ型を使用するか、キーと値を単一のオブジェクトに格納し、次にそのオブジェクトの配列を持つことです。

編集:あなたの質問を再読み込みした後、値をソートする必要性に基づいて、辞書があなたが望むデータタイプだとは思えません。しかし、私はまだキーと値を含むオブジェクトを持つことをお勧めします。値でソートし、キーが同期していないことを確認してください。

1

Array.Sort(値、キー)はデフォルトのComparerを使用して値とキーをソートします。記述していることを行うためにカスタムComparerを記述し、ComparerをArray.Sortメソッドに渡す必要があります。

0

これを値のペアの配列の並べ替えに変換することで、独自のコンパレータを提供して、並べ替えの動作を好きなようにすることができます。 (2つの別々の配列を使用するのは危険です)。http://msdn.microsoft.com/en-us/library/system.array.sort.aspxの4番目のメソッドを参照してください。

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; 
} 
関連する問題