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);
精彩评论