【问题标题】:Sorting two arrays (values,keys), then sorting the keys对两个数组(值、键)进行排序,然后对键进行排序
【发布时间】:2010-11-29 22:17:33
【问题描述】:

我有一个看似简单的问题,但到目前为止我无法弄清楚。

假设我有两个数组:

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

【问题讨论】:

    标签: c# arrays


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      一般来说,并行数组是不受欢迎的。数据很容易变得不同步。我建议要么使用 map/Dictionary 数据类型,要么将键和值存储在单个对象中,然后拥有所述对象的数组。

      编辑:重新阅读您的问题后,我不认为 Dictionary 是您想要的数据类型,这取决于您对值进行排序的需要。但是,我仍然建议拥有一个包含键和值的对象。然后,您可以按值排序,并确保它们的键不会不同步。

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          【解决方案4】:

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

          【讨论】:

            【解决方案5】:

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

            更好的是,声明一个命名类型来保存数据所有时间。并行数组通常不是一个好主意。出于性能或互操作性的原因,在某些小众场景中需要它们,否则应避免使用。

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

            例如:

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

            【讨论】:

              猜你喜欢
              • 2012-04-12
              • 1970-01-01
              • 2013-09-14
              • 1970-01-01
              • 1970-01-01
              • 2015-04-06
              相关资源
              最近更新 更多