[C#] 使用LINQ获取一个List <>中不在另一个List <>中的项目


Answers

如果你重写人的平等,那么你也可以使用:

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

此变体不会删除重复项。

Question

我会假设有一个简单的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)




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

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



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

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

我认为它与一些人所感兴趣的答案不同,甚至认为最有可能对列表而言不太理想。 现在对于带有索引ID的表格,这肯定是要走的路。




这是一个可以获得应聘者尚不具备的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);