简体   繁体   English

我可以使用LINQ检查列表中的对象是否具有唯一ID吗?

[英]Can I use LINQ to check if objects in a list have a unique ID?

say I have a list containing objects like this one: 说我有一个包含这样的对象的列表:

public class Person
{
    private string _name; 
    private string _id;
    private int _age;

    public Person 
    {
    }

    // Accessors
}

public class ManipulatePerson
{
    Person person = new Person();
    List<Person> personList = new List<Person>;

    // Assign values

    private void PopulateList();
    {
        // Loop 
        personList.Add(person);

        // Check if every Person has a unique ID
    }
}

and I wanted to check that each Person had a unique ID. 我想检查每个人都有一个唯一的ID。 I would like to return a boolean true/false depending on whether or not the IDs are unique. 我想返回一个布尔值true / false,具体取决于ID是否唯一。 Is this something I can achieve with LINQ? 这是我用LINQ可以实现的吗?

I would use Distinct and then check against the counts for example: 我会使用Distinct然后检查计数例如:

bool bAreAllPeopleUnique = (personList.Distinct(p => p.ID).Count == personList.Count);

However as @Ian commented you will need to add a property to the Person class so that you can access the Id like so: 但是,正如@Ian所述,您需要向Person类添加一个属性 ,以便您可以像这样访问Id:

public string ID
{
    get { return _id; }
}

A 'nicer' way to implement this would be to add a method like so: 实现这一目标的“更好”方法是添加如下方法:

private bool AreAllPeopleUnique(IEnumerable<Person> people)
{
    return (personList.Distinct(p => p.ID).Count == personList.Count);
}

NOTE: The method takes in an IEnumerable not a list so that any class implementing that interface can use the method. 注意:该方法接受IEnumerable而不是列表,以便实现该接口的任何类都可以使用该方法。

Note that you can even leverage directly an HashSet<> : 请注意,您甚至可以直接利用HashSet<>

var hs = new HashSet<string>();
bool areAllPeopleUnique = personList.All(x => hs.Add(x.Id));

(and is the code that I normally use) (这是我通常使用的代码)

It has the advantage that on the best case (presence of some duplicates) it will stop before analyzing all the personList collection. 它的优点是,在最佳情况下(存在一些重复),它将在分析所有personList集合之前停止。

One of best ways to do so is overriding Equals and GetHashCode , and implementing IEquatable<T> : 最好的方法之一是重写EqualsGetHashCode ,并实现IEquatable<T>

public class Person : IEquatable<Person>
{
     public string Id { get; set; }

     public override bool Equals(object some) => Equals(some as Person);
     public override bool GetHashCode() => Id != null ? Id.GetHashCode() : 0;
     public bool Equals(Person person) => person != null && person.UniqueId == UniqueId;
}

Now you can use HashSet<T> to store unique objects and it will be impossible that you store duplicates. 现在您可以使用HashSet<T>来存储唯一对象,并且您无法存储重复项。 And, in addition, if you try to add a duplicated item, Add will return false . 此外,如果您尝试添加重复项, Add将返回false

NOTE: My IEquatable<T> , and Equals / GetHashCode overrides are very basic, but this sample implementation should give you a good hint on how to elegantly handle your scenario. 注意:我的IEquatable<T>Equals / GetHashCode覆盖是非常基本的,但是此示例实现应该为您提供有关如何优雅地处理场景的良好提示。

You can check this Q&A to get an idea on how to implement GetHashCode What is the best algorithm for an overridden System.Object.GetHashCode? 您可以查看此问答以了解如何实现GetHashCode 对于重写的System.Object.GetHashCode,什么是最佳算法?

Maybe this other Q&A might be interesitng for you: Why is it important to override GetHashCode when Equals method is overridden? 也许这个其他问答可能会对你有意义: 为什么在重写Equals方法时重写GetHashCode很重要?

You can use GroupBy for getting unique items: 您可以使用GroupBy获取唯一项:

var result = personList.GroupBy(p=> p.Id)
                   .Select(grp => grp.First())
                   .ToList();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM