Jack
Jack

Reputation: 307

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. I would like to return a boolean true/false depending on whether or not the IDs are unique. Is this something I can achieve with LINQ?

Upvotes: 8

Views: 7172

Answers (4)

TheLethalCoder
TheLethalCoder

Reputation: 6744

I would use Distinct and then check against the counts for example:

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:

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.

Upvotes: 7

Mat&#237;as Fidemraizer
Mat&#237;as Fidemraizer

Reputation: 64923

One of best ways to do so is overriding Equals and GetHashCode, and implementing 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. And, in addition, if you try to add a duplicated item, Add will return 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.

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?

Maybe this other Q&A might be interesitng for you: Why is it important to override GetHashCode when Equals method is overridden?

Upvotes: 1

xanatos
xanatos

Reputation: 111860

Note that you can even leverage directly an 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.

Upvotes: 10

Sirwan Afifi
Sirwan Afifi

Reputation: 10824

You can use GroupBy for getting unique items:

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

Upvotes: 0

Related Questions