Use LINQ to get items in one List<>, that are not in another List<>
我假设有一个简单的LINQ查询来完成这项工作,我只是不确定如何完成。请参见下面的代码段。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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查询,把
1 | var result = peopleList2.Where(p => !peopleList1.Any(p2 => p2.ID == p.ID)); |
如果你忽视了人的平等,那么你也可以使用:
1 | peopleList2.Except(peopleList1) |
或者,如果您希望快速代码但不想覆盖相等:
1 2 | var excludedIDs = new HashSet<int>(peopleList1.Select(p => p.ID)); var result = peopleList2.Where(p => !excludedIDs.Contains(p.ID)); |
此变量不会删除重复项。
或者如果你不想否定:
1 | var result = peopleList2.Where(p => peopleList1.All(p2 => p2.ID != p.ID)); |
基本上,它说从peoplelist2获取所有信息,peoplelist1中的所有ID与peoplelist2中的ID不同。
只是有点不同于公认的答案:)
由于到目前为止所有的解决方案都使用了流畅的语法,下面是一个查询表达式语法的解决方案,适用于那些感兴趣的人:
1 2 3 4 5 6 7 | var peopleDifference = from person2 in peopleList2 where !( from person1 in peopleList1 select person1.ID ).Contains(person2.ID) select person2; |
我认为这与一些人感兴趣的答案完全不同,甚至认为这很可能是次优的列表。现在对于带有索引ID的表,这绝对是一种方法。
派对有点晚了,但一个很好的解决方案也是linq-to-sql兼容的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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
克劳斯的回答很好,但雷斯哈珀会要求你"简化LINQ表达式":
此可枚举扩展允许您定义要排除的项列表和用于查找用于执行比较的键的函数。
1 2 3 4 5 6 7 8 9 | 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))); } } |
你可以这样用
1 | list1.Exclude(list2, i => i.ID); |
一旦编写了通用的FunceQualityComparer,就可以在任何地方使用它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | peopleList2.Except(peopleList1, new FuncEqualityComparer<Person>((p, q) => p.ID == q.ID)); public class FuncEqualityComparer<T> : IEqualityComparer<T> { private readonly Func<T, T, bool> comparer; private readonly Func<T, int> hash; public FuncEqualityComparer(Func<T, T, bool> comparer) { this.comparer = comparer; if (typeof(T).GetMethod(nameof(object.GetHashCode)).DeclaringType == typeof(object)) hash = (_) => 0; else hash = t => t.GetHashCode(); } public bool Equals(T x, T y) => comparer(x, y); public int GetHashCode(T obj) => hash(obj); } |
首先,从集合Where条件中提取ID
1 | List<int> indexes_Yes = this.Contenido.Where(x => x.key == 'TEST').Select(x => x.Id).ToList(); |
其次,使用"比较"状态选择不同于所选内容的ID
1 | List<int> indexes_No = this.Contenido.Where(x => !indexes_Yes.Contains(x.Id)).Select(x => x.Id).ToList(); |
显然你可以用x.key!="测试",但只是一个例子
下面是一个工作示例,它可以让应聘者掌握一些IT技能已经有了。
1 2 3 4 5 6 7 8 9 | //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); |