如果通过比较项目的属性,集合尚未包含它,则将项目添加到集合中?

mic*_*ael 38 c# linq collections contains

基本上,我如何做到这一点,所以我可以做类似于:CurrentCollection.Contains(...),除了比较项目的属性是否已经在集合中?

public class Foo
{
    public Int32 bar;
}


ICollection<Foo> CurrentCollection;
ICollection<Foo> DownloadedItems;

//LINQ: Add any downloaded items where the bar Foo.bar is not already in the collection?
Run Code Online (Sandbox Code Playgroud)

R. *_*des 52

首先,您要查找集合中尚未包含的元素:

var newItems = DownloadedItems.Where(x => !CurrentCollection.Any(y => x.bar == y.bar));
Run Code Online (Sandbox Code Playgroud)

然后添加它们:

foreach(var item in newItems)
{
    CurrentCollection.Add(item);
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果大小DownloadedItems接近于大小,则第一个操作可能具有二次复杂度CurrentCollection.如果最终导致问题(首先测量!),您可以使用a HashSet将复杂性降低到线性:

// collect all existing values of the property bar
var existingValues = new HashSet<Foo>(from x in CurrentCollection select x.bar);
// pick items that have a property bar that doesn't exist yet
var newItems = DownloadedItems.Where(x => !existingValues.Contains(x.bar));
// Add them
foreach(var item in newItems)
{
    CurrentCollection.Add(item);
}
Run Code Online (Sandbox Code Playgroud)

  • 使用哈希映射方法使我的方法快了 5 倍。 (2认同)

Jum*_*zza 12

使用R.Martinho Fernandes方法并转换为1行:

CurrentCollection.AddRange(DownloadedItems.Where(x => !CurrentCollection.Any(y => y.bar== x.bar)));
Run Code Online (Sandbox Code Playgroud)


Yan*_*nga 10

您可以使用Enumerable.Except:

它将比较仅出现在第一个列表中的两个列表和返回元素.

CurrentCollection.AddRange(DownloadedItems.Except(CurrentCollection));
Run Code Online (Sandbox Code Playgroud)


hun*_*ter 5

您可以调用该Any方法并传递一个值以与集合中对象类型的任何属性进行比较

if (!CurrentCollection.Any(f => f.bar == someValue))
{
    // add item
}
Run Code Online (Sandbox Code Playgroud)

更完整的解决方案可能是:

DownloadedItems.Where(d => !CurrentCollection.Any(c => c.bar == d.bar)).ToList()
    .ForEach(f => CurrentCollection.Add(f));
Run Code Online (Sandbox Code Playgroud)