首页 > 解决方案 > 如何检查HashSet> 包含列表的重复值在 C# 中?

问题描述

我在 C# 中有一个 HashSet,如下所示:

HashSet<List<int>> _hash = new HashSet<List<int>>();

现在,我在其中插入了一个值,如下所示:

_hash.add(new List<int> {1,7});

当我在上面的代码之后编写以下代码时:

_hash.contains(new List<int>{1,7});

我期待它返回 true,因为刚刚添加了相同的值,但它确实返回了 false。这让我感到困惑。此外,我如何确保当我确实有一个 List 哈希集时,在我向其中添加任何新值之前其中没有重复项。

我认为使用 HashSet 背后的全部原因是为了避免任何重复,但似乎这个允许重复。

现在,从长远来看,我想要的只是当我有一个 List> 时,我如何确保进入 List> 的每个元素(List)都是唯一的?

标签: c#listduplicateshashset

解决方案


您可以创建自己的可比较的只读集合。

public class ComparableReadOnlyCollection<T> : ReadOnlyCollection<T>
{
    public ComparableReadOnlyCollection(IList<T> list)
        : base(list.ToArray())
    {
    }

    public override bool Equals(object other)
    {
        return
            other is IEnumerable<T> otherEnumerable &&
            otherEnumerable.SequenceEqual(this);
    }

    public override int GetHashCode()
    {
        int hash = 43;
        unchecked {
            foreach (T item in this) {
                hash = 19 * hash + item.GetHashCode();
            }
        }
        return hash;
    }
}

请注意,这ReadOnlyCollection<T>只是原始列表的包装。如果您修改此列表,则会ReadOnlyCollection<T>反映这些更改。我的实现将原始列表复制到一个数组以使其真正不可变。

但请注意,如果元素T是引用类型,您仍然可以修改原始对象的成员!所以要小心。

此测试按预期工作:

var hashSet = new HashSet<ComparableReadOnlyCollection<int>>();
hashSet.Add(new ComparableReadOnlyCollection<int>(new [] { 1, 7 }));

Console.WriteLine(hashSet.Contains(new ComparableReadOnlyCollection<int>(new [] { 1, 7 })));
Console.WriteLine(hashSet.Contains(new ComparableReadOnlyCollection<int>(new [] { 7, 1 })));
Console.WriteLine(hashSet.Contains(new ComparableReadOnlyCollection<int>(new [] { 1, 7, 0 })));

hashSet.Add(new ComparableReadOnlyCollection<int>(new [] { 1, 7 }));
hashSet.Add(new ComparableReadOnlyCollection<int>(new [] { 1, 7, 0 }));
hashSet.Add(new ComparableReadOnlyCollection<int>(new [] { 7, 1 }));
Console.WriteLine(hashSet.Count);
Console.ReadKey();

它打印

True
False
False
3

请注意,它不会打印 4,因为集合中不能有重复项。


第二种解决方案:

阅读您的编辑后,我不确定您真正想要什么。您的意思是创建 aHashSet<int>而不是 aHashSet<List<int>>并比较列表的元素而不是列表本身吗?

HashSet<int> _hash = new HashSet<int>(new List<int> { 1, 1, 2, 3, 5, 8, 13 });    

现在哈希集包含数字 { 1, 2, 3, 5, 8, 13 }。集合元素总是唯一的。

然后你可以测试

var hash2 = new HashSet<int> { 3, 8 };

if (_hash.IsSupersetOf(hash2)) {
    Console.WriteLine("_hash contains 3 and 8");
}

或者,什么是等价的:

if (hash2.IsSubsetOf(_hash)) {
    Console.WriteLine("_hash contains 3 and 8");
}

第三种解决方案:

一个List<HashSet<int>>呢?因为现在,您可以将集合操作应用于列表的每个元素(这是一个哈希集)。


推荐阅读