tags:

views:

126

answers:

3

I have a List<> of custom objects. This custom type has a property called Name which should be unique among the list. In other words, no 2 items items in the list should have the same value for their Name property.

When I validate this list, I want to retrieve the offending items. Is there a Linq operation which will allow me to do this?

I want to have something like

listOfItems.Where(x => x.Name.Equals(/*anything else in this list with the same value for name */)

Basically, I am trying to avoid checking the entire list against every item in the list (in a nested foreach):

private IList<ICustomObject> GetDuplicatedTypeNames(IList<ICustomObjects> customObjectsToFindDuplicatesIn)
    {
        var duplicatedList = new List<ICustomObject>();

        foreach(var customObject in customObjectsToFindDuplicatesIn)
            foreach(var innerCustomObject in customObjectsToFindDuplicatesIn)
                if (customObject == innerCustomObject && customObject .Name.Equals(innerCustomObject.Name))
                    duplicatedList.Add(customObject);

        return duplicatedList;
    }

(EDIT) NOTE: I am constrained to using a List<> by domain rules and using a Dictionary<> is not an option.

+3  A: 

Why not use a Dictionary instead of a List then, with the Name property as the Key? That way, you can't add duplicate names to the collection at all, as an exception would be thrown.

Furthermore, you can use the ContainsKey method to test if a name is already in the Dictionary before adding it.

The advantage of this approach is that it's much faster than scanning the List for duplicates.

Jean Azzopardi
My List is a the back end DataSource of a visual grid. The user edits values in the grid and I want validation to happen on the fly. A Dictionary would unnecessarily complicate the DataSource. Also I am restricted by this rule because of how the domain model works.
Corpsekicker
From the description, it seems to me that there's a `List` that allows dupes, and that the asker want to know what these dupes are
Abel
Fair enough, I didn't know that your situation didn't allow the use of a Dictionary.. but you should have specified that in the question.
Jean Azzopardi
+7  A: 

Get names of duplicates:

 var duplicates = listOfItems
        .GroupBy(i => i.Name)
        .Where(g => g.Count() > 1)
        .Select(g => g.Key);

Edit: Get duplicate items:

var duplicates = listOfItems
    .GroupBy(i => i.Name)
    .Where(g => g.Count() > 1)
    .SelectMany(g => g);
PHeiberg
This will only return the Names of the duplicates.
Nescio
Added code to get the duplicate elements
PHeiberg
A: 

This will return a list of objects

class foo
{
    public string Name { get; set; }

    public override string ToString()
    {
        return Name;
    }
}

class fooEqualityComparer : IEqualityComparer<foo>
{
    public bool Equals(foo x, foo y)
    {
        if (x == null || y == null)
            return false;
        return x.Name == y.Name;
    }

    public int GetHashCode(foo obj)
    {
        return obj.Name.GetHashCode();
    }
}


var duplicates = listOfItems
.GroupBy(x => x, new fooEqualityComparer())
.Where(g => g.Count() > 1)
.SelectMany(g => g);
rudnev