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

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的值已经交换,而值数组的顺序没有改变。

5个回答

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

Array.Sort(values,keys)会使用默认的比较器来对值和键进行排序。如果您想要实现自定义的排序方式,您需要编写一个自定义的比较器,并将其传递给Array.Sort方法。


0

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接