开发者

Is there a Linq operation to retrieve specific items from a list of items where the item has a property value for a property which should be unique?

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 che开发者_高级运维cking 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.


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);


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.


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);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜