将IEnumerable <type>添加到IList <type>,其中IList不包含主键 - LAMBDA </type> </type>

时间:2011-11-22 17:17:33

标签: c# .net lambda ienumerable ilist

我有IList<Price> SelectedPrices。我还有一个IEnumerable<Price>,可以在以后检索。我想添加从后者到前者的所有内容,前者不包含后者中定义的主键。例如:

IList<Price>包含Price.ID = 1Price.ID = 2IEnumerable<Price>包含Price.ID = 2Price.ID = 3Price.ID = 4。使用lambda添加这些项目的最简单方法是什么,以便最终得到包含4个唯一价格的IList?我知道我必须在ToList()上致电IList以获取对AddRange()方法的访问权限,以便我可以一次添加多个项目,但如何仅选择DON项目T存在于可枚举的列表中吗?

4 个答案:

答案 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);
        }
    }