如何在Dictionary <string,List <int >>中将List <int>分组,其中列表是相同的?

Dav*_*ers 2 .net c# linq

我想获取a 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);
Run Code Online (Sandbox Code Playgroud)

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

Tim*_*lds 6

那将在你的List<int>对象上使用参考比较.由于两个List<int>包含[1, 2, 3, 4, 5]都是单独实例化的,因此它们将具有不同的引用.

请尝试以下操作,例如:

var ListGroups = AllLists.GroupBy(p => string.Join(",", p.Value));
Run Code Online (Sandbox Code Playgroud)

这将按string您的列表的表示进行分组.请注意,这可能不是您想要做的,而且纯粹是示范性的.

您可以使用此重载的的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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是你如何使用它:

var ListGroups = AllLists.GroupBy(p => p.Value,
    new IEnumerableEqualityComparer<int>());
Run Code Online (Sandbox Code Playgroud)

请注意,因为它IEqualityComparer<T>是逆变的,T你可以使用上面的List<int>那个,因为它实现IEnumerable<int>.