首页 文章

使用LINQ获取一个List <>中的项目,这些项目不在另一个List <>中

提问于
浏览
409

我会假设有一个简单的LINQ查询来执行此操作,我只是不确定如何 . 请参阅下面的代码段 .

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

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

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

我想执行一个LINQ查询给我 peopleList2 中所有不在 peopleList1 中的人这个例子应该给我两个人(ID = 4&ID = 5)

9 回答

  • 5
    var result = peopleList2.Where(p => !peopleList1.Any(p2 => p2.ID == p.ID));
    
  • 718

    如果覆盖People的相等性,那么您也可以使用:

    peopleList2.Except(peopleList1)
    

    Except 应该明显快于 Where(...Any) 变体,因为它可以将第二个列表放入哈希表中 . Where(...Any) 的运行时间为 O(peopleList1.Count * peopleList2.Count) ,而基于 HashSet<T> (几乎)的变体的运行时间为 O(peopleList1.Count + peopleList2.Count) .

    Except 隐式删除重复项 . 这不应该影响你的情况,但可能是类似案件的问题 .

    或者,如果您想要快速代码但又不想覆盖相等性:

    var excludedIDs = new HashSet<int>(peopleList1.Select(p => p.ID));
    var result = peopleList2.Where(p => !excludedIDs.Contains(p.ID));
    

    此变体不会删除重复项 .

  • 49

    或者,如果你想要它没有否定:

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

    基本上它说来自peopleList2的所有内容,其中peopleList1中的所有ID都与peoplesList2中的id不同 .

    从接受的答案中略微不同的方法:)

  • 12

    由于迄今为止所有解决方案都使用了流畅的语法,因此这里是查询表达式语法的解决方案,对于那些感兴趣的人:

    var peopleDifference = 
      from person2 in peopleList2
      where !(
          from person1 in peopleList1 
          select person1.ID
        ).Contains(person2.ID)
      select person2;
    

    我认为它与某些人感兴趣的答案有所不同,甚至认为它很可能对列表来说不是最理想的 . 现在对于具有索引ID的表,这肯定是要走的路 .

  • 305

    派对迟到了,但Linq与SQL兼容的一个很好的解决方案是:

    List<string> list1 = new List<string>() { "1", "2", "3" };
    List<string> list2 = new List<string>() { "2", "4" };
    
    List<string> inList1ButNotList2 = (from o in list1
                                       join p in list2 on o equals p into t
                                       from od in t.DefaultIfEmpty()
                                       where od == null
                                       select o).ToList<string>();
    
    List<string> inList2ButNotList1 = (from o in list2
                                       join p in list1 on o equals p into t
                                       from od in t.DefaultIfEmpty()
                                       where od == null
                                       select o).ToList<string>();
    
    List<string> inBoth = (from o in list1
                           join p in list2 on o equals p into t
                           from od in t.DefaultIfEmpty()
                           where od != null
                           select od).ToList<string>();
    

    感谢http://www.dotnet-tricks.com/Tutorial/linq/UXPF181012-SQL-Joins-with-C

  • 28

    克劳斯的答案很棒,但ReSharper会要求你“简化LINQ表达”:

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

  • 0

    此Enumerable Extension允许您定义要排除的项列表以及用于查找用于执行比较的键的函数 .

    public static class EnumerableExtensions
    {
        public static IEnumerable<TSource> Exclude<TSource, TKey>(this IEnumerable<TSource> source,
        IEnumerable<TSource> exclude, Func<TSource, TKey> keySelector)
        {
           var excludedSet = new HashSet<TKey>(exclude.Select(keySelector));
           return source.Where(item => !excludedSet.Contains(keySelector(item)));
        }
    }
    

    你可以这样使用它

    list1.Exclude(list2, i => i.ID);
    
  • 6

    这是一个工作示例,可以获得求职者尚未拥有的IT技能 .

    //Get a list of skills from the Skill table
    IEnumerable<Skill> skillenum = skillrepository.Skill;
    //Get a list of skills the candidate has                   
    IEnumerable<CandSkill> candskillenum = candskillrepository.CandSkill
           .Where(p => p.Candidate_ID == Candidate_ID);             
    //Using the enum lists with LINQ filter out the skills not in the candidate skill list
    IEnumerable<Skill> skillenumresult = skillenum.Where(p => !candskillenum.Any(p2 => p2.Skill_ID == p.Skill_ID));
    //Assign the selectable list to a viewBag
    ViewBag.SelSkills = new SelectList(skillenumresult, "Skill_ID", "Skill_Name", 1);
    
  • 0

    首先,从条件集合中提取id

    List<int> indexes_Yes = this.Contenido.Where(x => x.key == 'TEST').Select(x => x.Id).ToList();
    

    第二,使用“比较”的东西选择不同于选择的ID

    List<int> indexes_No = this.Contenido.Where(x => !indexes_Yes.Contains(x.Id)).Select(x => x.Id).ToList();
    

    显然你可以使用x.key!=“TEST”,但这只是一个例子

相关问题