【问题标题】:Use LINQ to get items in one List<>, that are in another List<>使用 LINQ 获取一个 List<> 中的项目,这些项目位于另一个 List<> 中
【发布时间】:2023-03-22 05:43:02
【问题描述】:

我假设有一个简单的 LINQ 查询可以做到这一点,我只是不确定如何。请看下面的代码 sn-p,评论解释了我想做的事情:

class Program
{
  static void Main(string[] args)
  {
    List<Person> peopleList1 = new List<Person>();
    peopleList1.Add(new Person() { ID = 1 });
    peopleList1.Add(new Person() { ID = 2 });
    peopleList1.Add(new Person() { ID = 3 });
    peopleList1.Add(new Person() { ID = 4});
    peopleList1.Add(new Person() { ID = 5});

    List<Person> peopleList2 = new List<Person>();
    peopleList2.Add(new Person() { ID = 1 });
    peopleList2.Add(new Person() { ID = 4});


    //I would like to perform a LINQ query to give me only
    //those people in 'peopleList1' that are in 'peopleList2'
    //this example should give me two people (ID = 1& ID = 4)
  }
}


  class Person
  {
     public int ID { get; set; }
  }

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    var result = peopleList2.Where(p =&gt; peopleList1.Any(p2 =&gt; p2.ID == p.ID));

    【讨论】:

      【解决方案2】:

      您可以使用Where

      var result = peopleList1.Where(p => peopleList2.Any(p2 => p2.ID == p.ID));
      

      您也可以使用Intersect (var result = peopleList1.Intersect(peopleList2);),但这需要您实现一个额外的IEqualityComparer&lt;Person&gt; 或覆盖PersonEqualsGetHashCode 方法,即两个@987654329具有相同ID 的@ 实例被视为相等。 Intersect 否则会执行引用相等。

      【讨论】:

        【解决方案3】:

        我会在 ID 上加入两个列表:

        var inboth = from p1 in peopleList1
                     join p2 in peopleList2
                     on p1.ID equals p2.ID
                     select p1;
        List<Person> joinedList = inboth.ToList();
        

        相关:Why is LINQ JOIN so much faster than linking with WHERE?

        如果您要覆盖Equals + GetHashCode,您可以使用Intersect

        List<Person> joinedList = peopleList1.Intersect(peopleList2).ToList();
        

        或者您可以为Intersect 提供自定义IEqualityComparer&lt;Person&gt;

        public class  PersonIdComparer: IEqualityComparer<Person>
        {
            public bool Equals(Person x, Person y)
            {
                if(object.ReferenceEquals(x, y)) return true;
                if (x == null || y == null) return false;
        
                return x.ID == y.ID;
            }
        
            public int GetHashCode(Person obj)
            {
                return obj == null ? int.MinValue : obj.ID;
            }
        }
        

        现在可以这样使用了:

        List<Person> joinedList = peopleList1
             .Intersect(peopleList2, new PersonIdComparer())
             .ToList();
        

        Enumerable.JoinEnumerable.Intersect 都是有效的,因为它们使用的是集合。

        【讨论】:

        • 这是最好的答案。可悲的是,看看选票,没有人关心效率和以正确的方式做事。他们想要的只是一种更短/更简单的方式。可怜的软件用户:(+1
        【解决方案4】:
        Product[] fruits1 = { new Product { Name = "apple", Code = 9 }, 
                                   new Product { Name = "orange", Code = 4 },
                                    new Product { Name = "lemon", Code = 12 } };
        
            Product[] fruits2 = { new Product { Name = "apple", Code = 9 } };
        
            //Get all the elements from the first array
            //except for the elements from the second array.
        
            IEnumerable<Product> except =
                fruits1.Except(fruits2);
        
            foreach (var product in except)
                Console.WriteLine(product.Name + " " + product.Code);
        
            /*
              This code produces the following output:
        
              orange 4
              lemon 12
            */
        

        【讨论】:

          【解决方案5】:

          您可以使用Enumerable.Intersect

          var common = peopleList1.Intersect(peopleList2);
          

          【讨论】:

          • 不覆盖Equals+GethashCode就不行,所以目前不是很有帮助
          • 这只有在 Person 有一个重写的 Equals 方法时才有效,该方法将两个 Person 实例定义为相等(如果它们的 ID 相等)。
          • @RenéVogt: Intersect 在调用Equals 之前首先使用GetHashCode
          • 是的,这就是Intersect 的完整实施链接的原因:)
          【解决方案6】:

          您可以使用 LINQ 相交扩展方法。

          http://msdn.microsoft.com/en-us/library/bb460136(v=VS.100).aspx

          所以你会这样做:

          class Program
          {
            static void Main(string[] args)
            {
              List<Person> peopleList1 = new List<Person>();
              peopleList1.Add(new Person() { ID = 1 });
              peopleList1.Add(new Person() { ID = 2 });
              peopleList1.Add(new Person() { ID = 3 });
              peopleList1.Add(new Person() { ID = 4});
              peopleList1.Add(new Person() { ID = 5});
          
              List<Person> peopleList2 = new List<Person>();
              peopleList2.Add(new Person() { ID = 1 });
              peopleList2.Add(new Person() { ID = 4});
          
              var result = peopleList1.Intersect(peopleList2);
            }
          }
          

          只需覆盖 Person-Class 中的 Equals 方法。我想你可以比较那里的 id。

          【讨论】:

          • @RenéVogt 谢谢,没有完全考虑到这一点。但我将此添加到答案中。 :)
          猜你喜欢
          • 2011-04-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-03-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-02-16
          相关资源
          最近更新 更多