对两个数组(值,键)进行排序,然后对键进行排序

我有一个似乎是一个简单的问题,但到目前为止我无法弄明白。

说我有两个数组:

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值,并且值数组的顺序没有改变。

如果您不是非常需要“就地排序”,我建议使用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}; 

通常,并行arrays是不受欢迎的。 数据很容易变得不同步。 我建议使用map / Dictionary数据类型,或者将键和值存储在单个对象中,然后使用所述对象的数组。

编辑:在重新阅读您的问题后,根据您对值的排序需求,我不认为词典是您想要的数据类型。 不过,我仍然建议使用包含键和值的对象。 然后,您可以按值排序,并确保它们的键不会不同步。

Array.Sort(values,keys)将使用默认的Comparer对值和键进行排序。 您需要编写自定义Comparer来执行您所描述的操作,并将Comparer传递给Array.Sort方法。

通过将其转换为值对数组的排序,您可以提供自己的比较器,并使排序工作几乎任何您喜欢的方式。 (使用两个单独的数组似乎很危险。)请参阅http://msdn.microsoft.com/en-us/library/system.array.sort.aspx上的第四种方法。

我认为接受的答案很棒。 可以使用匿名类型,如答案中所示,或声明命名类型以在排序时保存数据。

更好的是,声明一个命名类型来始终保存数据。 并行数组通常不是一个好主意。 出于性能或可互操作性原因需要一些利基场景,但应避免使用它们。

也就是说,为了完整性,我认为指出数组可以“按代理”进行排序也是有用的。 即创建一个新数组,它只是原始数组的索引并对该数组进行排序。 对索引数组进行排序后,可以使用该数组直接访问原始数据,也可以使用该数组将原始数据复制到新的排序数组中。

例如:

 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; }