2010-11-29 86 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; 
}