【问题标题】:How to remove value that does not exist in another list?如何删除另一个列表中不存在的值?
【发布时间】:2018-07-28 22:15:02
【问题描述】:

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

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

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

这将返回 0。

记录是:

list_name | id
  master    1
  master    2
  master    3
  master    4
  master    5
  update    3
  update    4
  update    5

最后,master 列表应仅包含以下记录:3、4、5。

我做错了什么?

【问题讨论】:

  • master.RemoveAll(i => !update.Exists(k => k.id == i.id));

标签: c# linq


【解决方案1】:

首先,让我们修复您的代码 - 当update 中的任何 项与master 匹配时,您将删除,因此!= 应该是==

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

这就是你所需要的,比如 1000 项左右的列表。如果列表是 10,000 个项目,由于上述算法的 O(n2) 特性,这可能会变慢。您可以将 update 的 ID 放入 HashSet,并使用 Contains 以实现潜在的加速:

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

【讨论】:

  • 我喜欢性能提示,但我的列表最多可以获取 400 条记录,所以这对我来说不是问题
【解决方案2】:

您正在寻找:

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

【讨论】:

    【解决方案3】:

    您正在寻找的是Intersect 方法(有点扭曲)。你需要一个相等比较器。

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

    第一个解决方案:覆盖 Equals

    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
    

    【讨论】:

      【解决方案4】:

      您可以使用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
      

      【讨论】:

        【解决方案5】:

        试试这个

        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));
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-08-28
          • 2021-05-20
          • 1970-01-01
          • 2013-04-29
          • 2015-07-23
          • 2021-06-15
          相关资源
          最近更新 更多