如何删除另一个列表中不存在的值?

时间:2018-07-28 10:20:00

标签: c# linq

假设我有两个列表masterupdate,现在master列表包含一个表中所有可用的记录,而update列表仅包含{ {1}}需要更新。

我想从master列表中排除所有不在master列表中的记录,所以我尝试了:

update

这将返回0。

记录是:

master.RemoveAll(c => update.Any(x => x.Id != c.Id));

list_name | id master 1 master 2 master 3 master 4 master 5 update 3 update 4 update 5 列表的末尾应仅包含以下记录:3、4、5。

我做错了什么?

5 个答案:

答案 0 :(得分:4)

首先,让我们修复您的代码-如果update中的任何项与master相匹配,则将其删除,因此!=应该为==

master.RemoveAll(c => !update.Any(x => x.Id == c.Id));

这就是您想要的大约1000件商品的清单的全部。如果该列表是10,000个项目,则由于上述算法的O(n 2 )性质,这可能会变慢。您可以将update的ID放入HashSet中,并使用Contains进行加速:

var updateIds = new HashSet<int>(update.Select(u => u.Id));
master.RemoveAll(m => !updateId.Contains(m.Id));

答案 1 :(得分:2)

您正在寻找:

master.RemoveAll(c => !update.Any(x => x.Id == c.Id));

答案 2 :(得分:1)

您正在寻找的是方法Intersect(略有变化)。您需要一个相等比较器。

  

Intersect :通过使用默认的相等比较器比较值来生成两个序列的集合相交。

第一个解决方案:覆盖等于

Try it Online!

public class Item
{
    public int Id {get;set;}

    public override bool Equals(object obj)
    {
        var item = obj as Item;
        return item == null ? false : this.Id.Equals(item.Id);
    }

    public override int GetHashCode() => Id.GetHashCode();
}

public static void Main()
{
    var master = (new []{ 1, 2, 3, 4, 5}).Select(x => new Item {Id = x});
    var update = (new []{ 1, 3, 5}).Select(x => new Item {Id = x});

    // yes all you need is here
    master = master.Intersect(update);

    foreach (var item in master)
        Console.WriteLine(item.Id);
}

输出

1
3
5

第二个解决方案:创建自定义比较器

Try it Online!

public class Item
{
    public int Id { get; set; }
}

public static void Main()
{
    // example
    var master = (new []{ 1, 2, 3, 4, 5}).Select(x => new Item {Id = x});
    var update = (new []{ 1, 3, 5}).Select(x => new Item {Id = x});

    // everything happens here.
    var master = master.Intersect(update, new KeyEqualityComparer<Item>(s => s.Id));

    foreach (var item in master)
        Console.WriteLine(item.Id);
}

// Interset doest not know how to compare by property. This will help it.
public class KeyEqualityComparer<T> : IEqualityComparer<T>
{
    private readonly Func<T, object> keyExtractor;

    public KeyEqualityComparer(Func<T, object> keyExtractor) => keyExtractor = keyExtractor;
    public bool Equals(T x, T y)  => keyExtractor(x).Equals(this.keyExtractor(y));
    public int GetHashCode(T obj) => keyExtractor(obj).GetHashCode();
}

输出

1
3
5

答案 3 :(得分:0)

您可以使用Join模拟相交:

Try it Online!

public class Item
{
    public int Id { get; set; }
}

public static void Main()
{
    var master = (new []{ 1, 2, 3, 4, 5}).Select(x => new Item {Id = x});
    var update = (new []{ 1, 3, 5}).Select(x => new Item {Id = x});

    // we need to get all update's ids.
    master = master.Join(update.Select(x => x.Id), o => o.Id, id => id, (o, id) => o);

    foreach (var item in master)
    {
        Console.WriteLine(item.Id);
    }
}

输出

1
3
5

答案 4 :(得分:-1)

尝试一下

var listMaster = new List<Master>();
var listUpdate = new List<Update>();

listMaster.Add(new Master { ID = 1, Name = "Jai" });
listMaster.Add(new Master { ID = 2, Name = "Ram" });
listMaster.Add(new Master { ID = 3, Name = "Amit" });
listMaster.Add(new Master { ID = 4, Name = "Mohan" });
listMaster.Add(new Master { ID = 5, Name = "JAg" });

listUpdate.Add(new Update { ID = 1, Name = "JaiU" });
listUpdate.Add(new Update { ID = 2, Name = "RamU" });
listUpdate.Add(new Update { ID = 3, Name = "ShyamU" });

listMaster.RemoveAll(c => !listUpdate.Any(x => x.ID == c.ID));