【问题标题】:How to consolidate a Dictionary with multiple (three) keys by reducing one or more key and merging the multiple records (if any) into one single one?如何通过减少一个或多个键并将多个记录(如果有)合并为一个来合并具有多个(三个)键的字典?
【发布时间】:2013-10-21 11:19:20
【问题描述】:

我有一个具有以下定义的字典。

    Dictionary<int[], int> D = new Dictionary<int[], int>();

其中键是一个 3 元素数组。我以此为例来简化我的场景。 (在我自己的代码中,Key 是一个复杂的类对象,其中包含一个包含 3-7 个元素的 List。)

    int[] key;
    key = new int[] { 1, 1, 1 };
    D.Add(key, 1);
    key = new int[] { 1, 1, 2 };
    D.Add(key, 2);
    key = new int[] { 1, 1, 3 };
    D.Add(key, 3);
    key = new int[] { 1, 2, 4 };
    D.Add(key, 4);
    key = new int[] { 2, 1, 1 };
    D.Add(key, 5);
    key = new int[] { 2, 5, 1 };
    D.Add(key, 6);

我想要的是有一种方法来减少键的数量,即。而不是拥有三个元素的数组,我想要一个 2 元素数组作为键,并将所有多余的值合并为一个值,以便生成的 KeyValue 对应如下所示。 (减少键的第一个索引)

    {1 1, 6} //two instances of matching key of {1 1} resulted the value to have 1+5 =6
    {1 2, 2}
    {1 3, 3}
    {2 4, 4}
    {5 1, 6}

【问题讨论】:

  • 为什么是1+5 而不是1+2+3?为什么是1 2, 2 而不是1 2, 42 45 1 键是从哪里来的?这对我来说没有任何意义。
  • 我已从密钥列表中取出第一列。这给我留下了 KeyCollection 的第二列和第三列。如果我只从这两列中获取唯一对,我只会得到我发布的 5 个键,并且在这 5 个键中,只有 {1 1} 在我的原始字典的第一个和第五个元素有多个实例,值分别为 1 和 5。因此,当我希望字典合并时,这两个值应该聚合给我 1+5=6。

标签: c# linq collections dictionary key


【解决方案1】:

首先,您的字典可能无法按预期工作 - int[] 类型没有默认比较器,因此您的字典中的键不会是唯一的(1 1 1 键可以有两个元素例如)。要使其正常工作,您需要提供自定义 IEqualityComparer&lt;int[]&gt;。这也是使您的主要问题的解决方案发挥作用所必需的:

public class IntArrayEqualityComparer : IEqualityComparer<int[]>
{
    public bool Equals(int[] x, int[] y)
    {
        if (x.Length != y.Length)
        {        
            return false;
        }

        return x.Zip(y, (v1, v2) => v1 == v2).All(b => b);
    }

    public int GetHashCode(int[] x)
    {
        return 0;
    }
}

所以你应该按如下方式创建你的字典:

Dictionary<int[], int> D
    = new Dictionary<int[], int>(new IntArrayEqualityComparer());

回到主要问题,这里是如何达到预期的结果:

var result = D
    .GroupBy(
        kvp => kvp.Key.Skip(1).ToArray(),
        new IntArrayEqualityComparer())
    .ToDictionary(
        g => g.Key,
        g => g.Sum(x => x.Value));

【讨论】:

  • 谢谢,这应该给我一个工作的基础。欣赏回应。关于如何在 Key 是 List 对象的场景以及如果我想删除任何列的 List of key tupple 的情况下如何管理这一点的任何建议?
  • @spyronum 基本相同 - 首先,您必须为初始键和已删除列的键定义相等标准。从概念上讲,List&lt;T&gt;T[] 相同。
猜你喜欢
  • 1970-01-01
  • 2019-07-23
  • 2017-07-14
  • 2019-03-23
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 2019-09-18
  • 1970-01-01
相关资源
最近更新 更多