【问题标题】:Sort key arrays with duplicate keys [duplicate]使用重复键对键数组进行排序[重复]
【发布时间】:2016-05-21 04:47:59
【问题描述】:

所以我有三个数组。它们的长度相同,并且以这样的方式“链接”,例如,sums[52]prods[52]indexes[52] 一起构成一条信息。出于更长、更不有趣的原因,它们没有组合成二维或三维数组。

我正在尝试对它们进行排序,以使sums 有序,而其他两个仍然相连。我现在使用的代码如下:

Array.Sort(sums.ToArray(), prods);
Array.Sort(sums.ToArray(), indexes);
Array.Sort(sums);

非常简单——它根据sums 对其他两个排序,然后对sums 排序。

很遗憾,sums 有很多重复值。因此,以这种方式排序可能会导致如下结果:

SUMS     PRODUCTS     INDEXES
12       67           38
12       52           107
12       60           11
13       42           98
13       17           4
18       21           60

sums 按顺序完美排序,prodsindexes 都匹配。我想做的是对prods 进行第二次排序。由于sums 是“键数组”但有重复项,它只是以某种随机顺序抛出prods。这是我试图获得的结果:

SUMS     PRODUCTS     INDEXES
12       52           107
12       60           11
12       67           38
13       17           4
13       42           98
18       21           60

sums 已排序,prods 映射到它,然后进行二次排序,indexes 映射到它。

我可以做一些效率极低的某种循环,但是这种设置处理非常大的列表,效率很重要。有没有一种简单的方法可以做到这一点?我没有看到任何明显的检查文档或查找其他人对数组键排序的用途。

【问题讨论】:

标签: c# arrays sorting key


【解决方案1】:

你可以这样做:

class Item
{
    public int sum;
    public int prod;
    public int index;
}


int[] sums = new int[] { 12, 12, 12, 13, 13, 18 };
int[] prods = new int[] { 67, 52, 60, 42, 17, 21 };
 int[] indexes = new int[] { 38, 107, 11, 98, 4, 60 };

List<Item> Items = new List<Item>();
for (int i = 0; i < sums.Length; i++)
{
    Item Item = new Item();

    Item.sum = sums[i];
    Item.prod = prods[i];
    Item.index = indexes[i];

    Items.Add(Item);
}

Items = Items.OrderBy(I => I.sum).ThenBy(I => I.prod).ThenBy(I => I.index).ToList();

sums = Items.Select(I => I.sum).ToArray();
prods = Items.Select(I => I.prod).ToArray();
indexes= Items.Select(I => I.index).ToArray();

【讨论】:

  • 在我看来,OP 并没有要求将 indexes 作为排序的一部分。你的第二个ThenBy() 是不必要的。这也与这个问题重复的问题中接受的答案基本相同。
【解决方案2】:

内存密集型,但可能是一种有效的解决方案。

    var sums = new int[] { 12, 12, 12, 13, 13, 18 };
    var prods = new int[] { 67, 52, 60, 42, 17, 21 };
    var indexes = new int[] { 38, 107, 11, 98, 4, 60 };

    var grouped = indexes.Zip(sums, (first, second) => new { Index = first, Sum = second})
        .Zip(prods, (first, second) => new { Index = first.Index, Sum = first.Sum, Prod = second}).ToList();

    foreach (var group in grouped.OrderBy(g => g.Sum).ThenBy(g => g.Prod))
    {
        Console.WriteLine("{0}\t{1}\t{2}", group.Sum, group.Prod, group.Index);
    }   

结果

12  52  107
12  60  11
12  67  38
13  17  4
13  42  98
18  21  60

【讨论】:

  • 这类似于 Arvin 的解决方案 - 我想您需要澄清“高效”的含义,您是指速度吗?内存使用情况?
  • 这里没有理由使用Zip()。只需使用Select() 一次性将任意多个数组投影到一个匿名类型中。例如。 var grouped = indexes.Select((index, i) =&gt; new { Index = index, Sum = sums[i], Prod = prods[i] });。无论如何,我很难看出这与其他答案有何实质性不同。
  • 差别不大,按提交后我看到了Arvin的解决方案
  • 我同意你的 Zip 评论,选择更好
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-09
  • 1970-01-01
  • 2018-02-02
  • 2013-05-10
  • 2012-02-19
  • 1970-01-01
  • 2015-10-10
相关资源
最近更新 更多