2016-02-19 12 views
5

nói rằng tôi có một danh sách chứa các đối tượng như thế này:Tôi có thể sử dụng LINQ để kiểm tra xem các đối tượng trong danh sách có một ID duy nhất không?

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 
    } 
} 

và tôi muốn kiểm tra rằng mỗi người có một ID duy nhất. Tôi muốn trả về giá trị boolean true/false tùy thuộc vào việc ID có là duy nhất hay không. Đây có phải là thứ tôi có thể đạt được với LINQ không?

+3

Sử dụng nhóm bằng http: // stackoverflow .com/questions/7325278/group-by-in-linq – edc65

+4

Hoặc nếu không, hãy sử dụng 'Distinct' và' Count' nếu số khác. Nhưng trước hết, hãy đặt ID của bạn thành tài sản thay vì trường riêng tư. – Ian

Trả lời

4

Lưu ý rằng bạn thậm chí có thể tận dụng trực tiếp một HashSet<>:

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

(và là mã mà tôi thường sử dụng)

Nó có lợi thế là trên trường hợp tốt nhất (sự hiện diện của một số bản sao) nó sẽ dừng lại trước khi phân tích tất cả các personList coll ection.

+0

Giao lộ, xin vui lòng! : D –

+0

Điều này là tốt, nhưng thậm chí tốt hơn sẽ là ghi đè lên hashcode và sau đó bạn có thể làm điều đó trực tiếp var hs = new HashSet (); – user853710

+0

@ user853710 Hoặc bạn có thể tạo một 'IEqualityComparer <>' riêng biệt với 'GetHashCode' đặc biệt. – xanatos

6

Tôi sẽ sử dụng Distinct và sau đó kiểm tra chống lại đếm ví dụ:

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

Tuy nhiên như @Ian nhận xét, bạn sẽ cần phải thêm một property đến lớp Person để bạn có thể truy cập vào Id như vậy:

public string ID 
{ 
    get { return _id; } 
} 

một cách 'đẹp' để thực hiện điều này sẽ có thêm một phương pháp như vậy:

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

LƯU Ý: Phương thức này có trong một IEnumerable không phải danh sách để bất kỳ lớp nào triển khai giao diện đó có thể sử dụng phương thức.

0

Bạn có thể sử dụng GroupBy để nhận vật phẩm độc đáo:

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

Bạn có thể sử dụng Khóa tổng hợp.Trên 100 bản ghi K, đây là một cải tiến đáng kể Chọn (grp => grp.Key) – user853710

1

Một trong những cách tốt nhất để làm điều đó là trọng EqualsGetHashCode, và thực hiện 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; 
} 

Bây giờ bạn có thể sử dụng để lưu trữ HashSet<T>đối tượng độc đáo và nó sẽ không thể mà bạn lưu trữ các bản sao. Ngoài ra, nếu bạn cố gắng thêm một mục trùng lặp, Add sẽ trả lại false.

LƯU Ý: My IEquatable<T>, và Equals/GetHashCode ghi đè là rất cơ bản, nhưng việc thực hiện mẫu này sẽ cho bạn một gợi ý tốt về cách xử lý thanh lịch kịch bản của bạn.

Bạn có thể kiểm tra Q này & Một để có được một ý tưởng về làm thế nào để thực hiện GetHashCodeWhat is the best algorithm for an overridden System.Object.GetHashCode?

lẽ khác Q này & A có thể được interesitng cho bạn: Why is it important to override GetHashCode when Equals method is overridden?

Các vấn đề liên quan