在foreach循环中,我想将产品添加到列表中,但我希望此列表不包含重复的产品,目前我已经解决了两个想法。
1/在循环中,在将产品添加到列表之前,我会检查该产品是否已经存在于列表中,否则我会将其添加到列表中。
foreach (var product in products)
{
// code logic
if(!listProduct.Any(x => x.Id == product.Id))
{
listProduct.Add(product);
}
}
2/。在循环中,即使有重复的产品,我也会将所有产品添加到列表中。然后在循环之外,我将使用Distinct来删除重复的记录。
foreach (var product in products)
{
// code logic
listProduct.Add(product);
}
listProduct = listProduct.Distinct().ToList();
我想知道这两种方式是最有效的。或者有其他想法可以将记录添加到列表中以避免重复??
我会选择第三种方法:哈希集它有一个接受IEnumerable
的构造函数重载。此构造函数删除重复项:
如果输入集合包含重复项,则集合将包含一个每个独特元素。不会引发任何异常。
来源:HashSet<T>
Constructor
用法:
List<Product> myProducts = ...;
var setOfProducts = new HashSet<Product>(myProducts);
去除重复后,setOfProducts[4]
就没有了正确的含义。
因此,HashSet不是IList<Product>
,而是ICollection<Product>
,您可以使用List进行计数/添加/删除等操作。你唯一不能做的就是通过索引获取
您首先要了解哪些元素不在集合中:
var newProducts = products.Where(x => !listProduct.Any(y => x.Id == y.Id));
然后使用AddRang 添加它们
listProduct.AddRagne(newItems)
或者你也可以使用foreach循环太
foreach (var product in newProducts)
{
listProduct.Add(product);
}
1更简单的解决方案是无需使用Distint
var newProductList = products.Union(listProduct).ToList();
但工会的表现并不好。
根据所包含的内容,您将所有内容都存储在内存中。如果是这种情况,或者只有在准备好之后才进行持久化,则可以考虑使用BinarySearch:https://msdn.microsoft.com/en-us/library/w4e7fxsh(v=vs.110(.aspx,最后还会得到一个有序列表。如果排序不重要,您可以使用HashSet,它非常快速,并且专门用于此目的。
同时检查:https://www.dotnetperls.com/hashset
这应该很快,可以处理任何订单:
// build a HashSet of your primary keys type (I'm assuming integers here) containing all your list elements' keys
var hashSet = new HashSet<int>(listProduct.Select(p => p.Id));
// add all items from the products list whose Id can be added to the hashSet (so it's not a duplicate)
listProduct.AddRange(products.Where(p => hashSet.Add(p.Id)));
不过,您可能需要考虑的是在Product
类型上实现IEquatable<Product>
并重写GetHashCode()
,这将使上面的代码更容易,并将相等性检查放在它们应该在的位置(在相应的类型内(:
var hashSet = new HashSet<int>(listProduct);
listProduct.AddRange(products.Where(hashSet.Add));