我有IList<Price> SelectedPrices
。我还有一个IEnumerable<Price>
,可以在以后检索。我想添加从后者到前者的所有内容,前者不包含后者中定义的主键。例如:
IList<Price>
包含Price.ID = 1
,Price.ID = 2
和IEnumerable<Price>
包含Price.ID = 2
,Price.ID = 3
和Price.ID = 4
。使用lambda添加这些项目的最简单方法是什么,以便最终得到包含4个唯一价格的IList
?我知道我必须在ToList()
上致电IList
以获取对AddRange()
方法的访问权限,以便我可以一次添加多个项目,但如何仅选择DON项目T存在于可枚举的列表中吗?
答案 0 :(得分:4)
我知道我必须在IList上调用ToList()才能访问AddRange()方法
这实际上并不安全。这将创建新 List<T>
,因此您不会将这些项目添加到原始IList<T>
。您需要一次添加一个。
最简单的选择就是循环并使用contains:
var itemsToAdd = enumerablePrices.Where(p => !SelectedPrices.Any(sel => sel.ID == p.ID));
foreach(var item in itemsToAdd)
{
SelectedPrices.Add(item);
}
然而,这本质上是二次的,所以如果集合非常大,它可能会很慢。根据集合的大小,实际上可能更好地提前构建一组ID:
var existing = new HashSet<int>(SelectedPrices.Select(p => p.ID));
var itemsToAdd = enumerablePrices.Where(p => !existing.Contains(p.ID));
foreach(var item in itemsToAdd)
{
SelectedPrices.Add(item);
}
如果您的集合(SelectedPrices
)很大,这将阻止例程进入二次方。
答案 1 :(得分:1)
尝试使用yourEnumerable.Where(x => !yourList.Any(y => y.ID == x.ID))
作为问题的选择部分。
答案 2 :(得分:1)
您可以尝试:
var newPrices = prices.Where(p => !SelectedPrices.Any(sp => sp.ID == p.ID));
foreach(var p in newPrices)
SelectedPrices.Add(p);
我知道我必须在IList上调用ToList()才能访问AddRange()方法,这样我就可以一次添加多个项目
ToList
将创建List<Price>
的新实例,因此您将修改另一个列表,而不是原始列表...不,您需要逐个添加项目。
答案 3 :(得分:1)
如果要将新元素添加到现有列表中并以最高效的方式执行此操作,则应该以常规方式执行此操作。像这样:
IList<Price> selectedPrices = ...;
IEnumerable<Price> additionalPrices = ...;
IDictionary<int, Price> pricesById = new Dictionary<int, Price>();
foreach (var price in selectedPrices)
{
pricesById.Add(price.Id, price);
}
foreach (var price in additionalPrices)
{
if (!pricesById.ContainsKey(price.Id))
{
selectedPrices.Add(price);
}
}