我有一个似乎是一个简单的问题,但到目前为止我无法弄明白。
说我有两个数组:
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值,并且值数组的顺序没有改变。
答案 0 :(得分: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};
答案 1 :(得分:1)
通常,并行数组不受欢迎。数据很容易变得不同步。我建议使用map / Dictionary数据类型,或者将键和值存储在单个对象中,然后使用所述对象的数组。
编辑:在重新阅读您的问题之后,根据您对值的排序需求,我不认为词典是您想要的数据类型。不过,我仍然建议使用包含键和值的对象。然后,您可以按值排序,并确保它们的密钥不会不同步。
答案 2 :(得分:1)
Array.Sort(values,keys)将使用默认的Comparer对值和键进行排序。您需要编写自定义Comparer来执行您所描述的操作,并将Comparer传递给Array.Sort方法。
答案 3 :(得分:0)
通过将其转换为值对数组的排序,您可以提供自己的比较器,并使排序工作几乎任何您喜欢的方式。 (使用两个单独的数组似乎很危险。)请参阅http://msdn.microsoft.com/en-us/library/system.array.sort.aspx处的第四种方法。
答案 4 :(得分:0)
我认为接受的答案很棒。可以使用匿名类型,如答案中所示,或声明命名类型以在排序时保存数据。
更好的是,声明一个命名类型来保存数据 all 的时间。并行数组通常不是一个好主意。有一些利基场景,出于性能或互操作性原因需要它们,但是否则应该避免它们。
那就是说,为了完整起见,我认为指出数组可以“按代理”排序也是有用的。即创建一个新数组,它只是原始数组的索引,并对那个数组进行排序。对索引数组进行排序后,您可以使用该数组直接访问原始数据,也可以使用该数组将原始数据复制到新的排序数组中。
例如:
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;
}