.NET 中仅允许唯一项目的集合?

发布于 2024-10-19 12:43:56 字数 1086 浏览 1 评论 0原文

C# 中是否有一个集合不允许您向其中添加重复项?例如,使用

public class Customer {
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { get; set; }

    public override int GetHashCode() {
        return (FirstName + LastName + Address).GetHashCode();
    }

    public override bool Equals(object obj) {
        Customer C = obj as Customer;
        return C != null && String.Equals(this.FirstName, C.FirstName) && String.Equals(this.LastName, C.LastName) && String.Equals(this.Address, C.Address);
    }
}

以下代码的愚蠢类(显然)会抛出异常:

Customer Adam = new Customer { Address = "A", FirstName = "Adam", LastName = "" };
Customer AdamDup = new Customer { Address = "A", FirstName = "Adam", LastName = "" };

Dictionary<Customer, bool> CustomerHash = new Dictionary<Customer, bool>();
CustomerHash.Add(Adam, true);
CustomerHash.Add(AdamDup, true);

但是是否有一个类可以类似地保证唯一性,但没有 KeyValuePairs?我认为 HashSet 会做到这一点,但阅读文档后,类似乎只是一个集合实现(去计算)。

Is there a collection in C# that will not let you add duplicate items to it? For example, with the silly class of

public class Customer {
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { get; set; }

    public override int GetHashCode() {
        return (FirstName + LastName + Address).GetHashCode();
    }

    public override bool Equals(object obj) {
        Customer C = obj as Customer;
        return C != null && String.Equals(this.FirstName, C.FirstName) && String.Equals(this.LastName, C.LastName) && String.Equals(this.Address, C.Address);
    }
}

The following code will (obviously) throw an exception:

Customer Adam = new Customer { Address = "A", FirstName = "Adam", LastName = "" };
Customer AdamDup = new Customer { Address = "A", FirstName = "Adam", LastName = "" };

Dictionary<Customer, bool> CustomerHash = new Dictionary<Customer, bool>();
CustomerHash.Add(Adam, true);
CustomerHash.Add(AdamDup, true);

But is there a class that will similarly guarantee uniqueness, but without KeyValuePairs? I thought HashSet<T> would do that, but having read the docs it seems that class is just a set implementation (go figure).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

挖鼻大婶 2024-10-26 12:43:56

HashSet 就是您要寻找的。来自 MSDN(添加了重点):

HashSet 类提供高性能的集合操作。集合是不包含重复元素的集合,并且其元素没有特定的顺序。

请注意 HashSet.Add(T item) 方法 如果该项目已添加到集合中,则返回 bool -- true;如果该项目已存在,则 false

HashSet<T> is what you're looking for. From MSDN (emphasis added):

The HashSet<T> class provides high-performance set operations. A set is a collection that contains no duplicate elements, and whose elements are in no particular order.

Note that the HashSet<T>.Add(T item) method returns a bool -- true if the item was added to the collection; false if the item was already present.

灼痛 2024-10-26 12:43:56

只在 HashSet 上添加一个扩展方法怎么样?

public static void AddOrThrow<T>(this HashSet<T> hash, T item)
{
    if (!hash.Add(item))
        throw new ValueExistingException();
}

How about just an extension method on HashSet?

public static void AddOrThrow<T>(this HashSet<T> hash, T item)
{
    if (!hash.Add(item))
        throw new ValueExistingException();
}
看透却不说透 2024-10-26 12:43:56

从 MSDN 上的 HashSet页面:

HashSet(Of T) 类提供高性能的集合操作。 集合是不包含重复元素的集合,并且其元素没有特定的顺序。

(强调我的)

From the HashSet<T> page on MSDN:

The HashSet(Of T) class provides high-performance set operations. A set is a collection that contains no duplicate elements, and whose elements are in no particular order.

(emphasis mine)

浅忆流年 2024-10-26 12:43:56

如果您需要的只是确保元素的唯一性,那么 HashSet 就是您所需要的。

当你说“只是一套实施”时,你是什么意思?集合(根据定义)是不保存元素顺序的唯一元素的集合。

If all you need is to ensure uniqueness of elements, then HashSet is what you need.

What do you mean when you say "just a set implementation"? A set is (by definition) a collection of unique elements that doesn't save element order.

我的黑色迷你裙 2024-10-26 12:43:56

只是添加我的 2 美分...

如果您需要一个 ValueExistingException 抛出 HashSet 您还可以轻松创建您的集合:

public class ThrowingHashSet<T> : ICollection<T>
{
    private HashSet<T> innerHash = new HashSet<T>();

    public void Add(T item)
    {
        if (!innerHash.Add(item))
            throw new ValueExistingException();
    }

    public void Clear()
    {
        innerHash.Clear();
    }

    public bool Contains(T item)
    {
        return innerHash.Contains(item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        innerHash.CopyTo(array, arrayIndex);
    }

    public int Count
    {
        get { return innerHash.Count; }
    }

    public bool IsReadOnly
    {
        get { return false; }
    }

    public bool Remove(T item)
    {
        return innerHash.Remove(item);
    }

    public IEnumerator<T> GetEnumerator()
    {
        return innerHash.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

例如,如果您在很多地方需要它,这可能很有用。 。

Just to add my 2 cents...

if you need a ValueExistingException-throwing HashSet<T> you can also create your collection easily:

public class ThrowingHashSet<T> : ICollection<T>
{
    private HashSet<T> innerHash = new HashSet<T>();

    public void Add(T item)
    {
        if (!innerHash.Add(item))
            throw new ValueExistingException();
    }

    public void Clear()
    {
        innerHash.Clear();
    }

    public bool Contains(T item)
    {
        return innerHash.Contains(item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        innerHash.CopyTo(array, arrayIndex);
    }

    public int Count
    {
        get { return innerHash.Count; }
    }

    public bool IsReadOnly
    {
        get { return false; }
    }

    public bool Remove(T item)
    {
        return innerHash.Remove(item);
    }

    public IEnumerator<T> GetEnumerator()
    {
        return innerHash.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

this can be useful for example if you need it in many places...

心碎的声音 2024-10-26 12:43:56

您可以尝试 HashSet

You can try HashSet<T>

街角迷惘 2024-10-26 12:43:56

您可以查看某种唯一列表,如下所示

public class UniqueList<T>
{
    public List<T> List
    {
        get;
        private set;
    }
    List<T> _internalList;

    public static UniqueList<T> NewList
    {
        get
        {
            return new UniqueList<T>();
        }
    }

    private UniqueList()
    {            
        _internalList = new List<T>();
        List = new List<T>();
    }

    public void Add(T value)
    {
        List.Clear();
        _internalList.Add(value);
        List.AddRange(_internalList.Distinct());
        //return List;
    }

    public void Add(params T[] values)
    {
        List.Clear();
        _internalList.AddRange(values);
        List.AddRange(_internalList.Distinct());
       // return List;
    }

    public bool Has(T value)
    {
        return List.Contains(value);
    }
}

,并且可以像下面这样使用它,

var uniquelist = UniqueList<string>.NewList;
uniquelist.Add("abc","def","ghi","jkl","mno");
uniquelist.Add("abc","jkl");
var _myList = uniquelist.List;

即使在重复项被添加到其中

You may look into something kind of Unique List as follows

public class UniqueList<T>
{
    public List<T> List
    {
        get;
        private set;
    }
    List<T> _internalList;

    public static UniqueList<T> NewList
    {
        get
        {
            return new UniqueList<T>();
        }
    }

    private UniqueList()
    {            
        _internalList = new List<T>();
        List = new List<T>();
    }

    public void Add(T value)
    {
        List.Clear();
        _internalList.Add(value);
        List.AddRange(_internalList.Distinct());
        //return List;
    }

    public void Add(params T[] values)
    {
        List.Clear();
        _internalList.AddRange(values);
        List.AddRange(_internalList.Distinct());
       // return List;
    }

    public bool Has(T value)
    {
        return List.Contains(value);
    }
}

and you can use it like follows

var uniquelist = UniqueList<string>.NewList;
uniquelist.Add("abc","def","ghi","jkl","mno");
uniquelist.Add("abc","jkl");
var _myList = uniquelist.List;

will only return "abc","def","ghi","jkl","mno" always even when duplicates are added to it

煮酒 2024-10-26 12:43:56

作为整体检查的不同方法,这里有 4 种方法来检查集合是否没有任何重复项:

public static bool LinqAny<T>(IEnumerable<T> enumerable)
{
    HashSet<T> set = new();

    return enumerable.Any(element => !set.Add(element));
}

public static bool LinqAll<T>(IEnumerable<T> enumerable)
{
    HashSet<T> set = new();

    return !enumerable.All(set.Add);
}

public static bool LinqDistinct<T>(IEnumerable<T> enumerable)
{
    return enumerable.Distinct().Count() != enumerable.Count();
}

public static bool ToHashSet<T>(IEnumerable<T> enumerable)
{
    return enumerable.ToHashSet().Count != enumerable.Count();
}

As an overall check different methods here are 4 ways to check if the collection has not any duplicates:

public static bool LinqAny<T>(IEnumerable<T> enumerable)
{
    HashSet<T> set = new();

    return enumerable.Any(element => !set.Add(element));
}

public static bool LinqAll<T>(IEnumerable<T> enumerable)
{
    HashSet<T> set = new();

    return !enumerable.All(set.Add);
}

public static bool LinqDistinct<T>(IEnumerable<T> enumerable)
{
    return enumerable.Distinct().Count() != enumerable.Count();
}

public static bool ToHashSet<T>(IEnumerable<T> enumerable)
{
    return enumerable.ToHashSet().Count != enumerable.Count();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文