LINQ를 사용하여 하나의 List <>에서 다른 List <>에없는 항목을 가져옵니다.
이 작업을 수행하는 간단한 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)
var result = peopleList2.Where(p => !peopleList1.Any(p2 => p2.ID == p.ID));
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));
이 변형은 중복을 제거하지 않습니다.
또는 부정없이 원한다면 :
var result = peopleList2.Where(p => peopleList1.All(p2 => p2.ID != p.ID));
기본적으로 peopleList1의 모든 ID가 peoplesList2의 id와 다른 peopleList2에서 모두 가져옵니다.
허용 된 답변과 약간 다른 접근 방식 :)
지금까지 모든 솔루션이 유창한 구문을 사용했기 때문에 다음은 관심있는 사용자를위한 쿼리 표현식 구문의 솔루션입니다.
var peopleDifference =
from person2 in peopleList2
where !(
from person1 in peopleList1
select person1.ID
).Contains(person2.ID)
select person2;
나는 그것이 일부 사람들에게 관심을 가질만한 대답과 충분히 다르다고 생각하며 심지어 목록에 대해 차선책이라고 생각했습니다. 이제 색인화 된 ID가있는 테이블의 경우 이것이 확실합니다.
파티에 늦었지만 Linq to 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에 대한 조언
클라우스의 대답은 훌륭했지만 ReSharper는 "LINQ 표현 단순화"를 요청합니다.
var result = peopleList2.Where(p => peopleList1.All(p2 => p2.ID != p.ID));
이 열거 가능 확장 기능을 사용하면 제외 할 항목 목록과 비교를 수행하는 데 사용할 키를 찾는 데 사용할 함수를 정의 할 수 있습니다.
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);
다음은 구직자에게없는 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);
먼저 조건이있는 컬렉션에서 ID를 추출합니다.
List<int> indexes_Yes = this.Contenido.Where(x => x.key == 'TEST').Select(x => x.Id).ToList();
둘째, "비교"estament를 사용하여 선택과 다른 ID를 선택하십시오.
List<int> indexes_No = this.Contenido.Where(x => !indexes_Yes.Contains(x.Id)).Select(x => x.Id).ToList();
분명히 x.key! = "TEST"를 사용할 수 있지만 단지 예일뿐입니다
일반 FuncEqualityComparer를 작성하면 어디서나 사용할 수 있습니다.
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);
}
'development' 카테고리의 다른 글
"[False, True]의 not (True)"이 False를 반환하는 이유는 무엇입니까? (0) | 2020.02.14 |
---|---|
ArithmeticException :“비 종료 소수점 확장; (0) | 2020.02.14 |
개체가 비어 있습니까? (0) | 2020.02.14 |
MySQL에서 정규 표현식을 바꾸는 방법은 무엇입니까? (0) | 2020.02.14 |
부호없는 int와 size_t (0) | 2020.02.14 |