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

时间:2010-11-29 22:17:33

标签: c# arrays

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

说我有两个数组:

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

5 个答案:

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