如何按字典<List,list <int =“”>&gt;中的List <int>进行分组?列表是否相同?</string,> </int>

时间:2014-03-20 17:55:44

标签: c# .net linq

我想获取Dictionary<string, List<int>>,然后为字典中的所有重复列表创建组。

Dictionary<string, List<int>> AllLists = new Dictionary<string, List<int>>()
{
    {"one", new List<int>() {1, 2, 3, 4, 5}},
    {"two", new List<int>() {1, 2, 3, 4, 5}},
    {"three", new List<int>() {1, 1, 1, 1, 1}}
};

var ListGroups = AllLists.GroupBy(p => p.Value);

这应该将具有匹配列表的字典索引分组到它们自己的组中,但它只是为字典中的每个索引创建一个组。我做错了什么?

1 个答案:

答案 0 :(得分:6)

您将在List<int>个对象上使用参考比较。由于包含List<int>的{​​{1}}都是单独实例化的,因此它们将具有不同的引用。

尝试以下方法,例如:

[1, 2, 3, 4, 5]

这将按您的列表的var ListGroups = AllLists.GroupBy(p => string.Join(",", p.Value)); 个表示进行分组。请注意,这可能是您想要做的事情,纯粹是示范性的。

您可以使用string方法的this overload来传递使用GroupBy实际查看列表内容的自定义IEqualityComparer<List<int>>

这里是Enumerable.SequenceEqual

IEqualityComparer<IEnumerable<T>>

以下是你如何使用它:

class IEnumerableEqualityComparer<T> : IEqualityComparer<IEnumerable<T>>
{
    public bool Equals(IEnumerable<T> a, IEnumerable<T> b)
    {
        return Enumerable.SequenceEqual(a, b);
    }

    public int GetHashCode(IEnumerable<T> source)
    {
        if (source == null)
        {
            return 0;
        }
        int shift = 0;
        int result = 1;
        foreach (var item in source)
        {
            int hash = item != null ? item.GetHashCode() : 17;
            result ^= (hash << shift)
                    | (hash >> (32 - shift))
                    & (1 << shift - 1);
            shift = (shift + 1) % 32;
        }
        return result;
    }
}

请注意,由于var ListGroups = AllLists.GroupBy(p => p.Value, new IEnumerableEqualityComparer<int>()); 中的IEqualityComparer<T>是逆变的,因此您可以将T用于List<int>,因为它实现了IEnumerable<int>