Ich würde davon ausgehen, dass es eine einfache LINQ-Abfrage gibt, ich bin nur nicht ganz sicher, wie. Bitte sehen Sie den Code-Ausschnitt unten.
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; }
}
Ich möchte eine LINQ-Abfrage durchführen, um mir alle Personen in peopleList2
zu geben, die sich nicht in peopleList1
befinden. Dieses Beispiel sollte mir zwei Personen (ID = 4 & ID = 5)
var result = peopleList2.Where(p => !peopleList1.Any(p2 => p2.ID == p.ID));
Wenn Sie die Gleichheit der Personen überschreiben, können Sie auch Folgendes verwenden:
peopleList2.Except(peopleList1)
Except
sollte deutlich schneller als die Where(...Any)
-Variante sein, da sie die zweite Liste in eine Hashtabelle setzen kann. Where(...Any)
hat eine Laufzeit von O(peopleList1.Count * peopleList2.Count)
, wohingegen Varianten, die auf HashSet<T>
(fast) basieren, eine Laufzeit von O(peopleList1.Count + peopleList2.Count)
haben.
Except
entfernt implizit Duplikate. Das sollte sich nicht auf Ihren Fall auswirken, könnte aber für ähnliche Fälle ein Problem sein.
Oder wenn Sie schnellen Code wünschen, die Gleichheit jedoch nicht überschreiben möchten:
var excludedIDs = new HashSet<int>(peopleList1.Select(p => p.ID));
var result = peopleList2.Where(p => !excludedIDs.Contains(p.ID));
Diese Variante entfernt keine Duplikate.
Oder wenn Sie es ohne Verneinung wollen:
var result = peopleList2.Where(p => peopleList1.All(p2 => p2.ID != p.ID));
Grundsätzlich heißt es, holen Sie sich alle von peopleList2, wobei sich alle IDs in peopleList1 von id in peopleList2 unterscheiden.
Nur ein bisschen anders als die akzeptierte Antwort :)
Da alle Lösungen bis jetzt eine fließende Syntax verwendet haben, finden Sie hier eine Lösung in der Abfrageausdruckssyntax:
var peopleDifference =
from person2 in peopleList2
where !(
from person1 in peopleList1
select person1.ID
).Contains(person2.ID)
select person2;
Ich denke, es unterscheidet sich genug von den Antworten, um für einige von Interesse zu sein, selbst wenn man bedenkt, dass es höchstwahrscheinlich für Listen suboptimal wäre. Für Tabellen mit indizierten IDs wäre dies definitiv der richtige Weg.
Etwas spät zur Party, aber eine gute Lösung, die auch Linq to SQL kompatibel ist, ist:
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>();
Dank an http://www.dotnet-tricks.com/Tutorial/linq/UXPF181012-SQL-Joins-with-C
Klaus 'Antwort war großartig, aber ReSharper fordert Sie auf, den LINQ-Ausdruck zu vereinfachen:
var result = peopleList2.Where(p => peopleList1.All(p2 => p2.ID != p.ID));
Mit dieser Enumerable-Erweiterung können Sie eine Liste von Elementen definieren, die ausgeschlossen werden sollen, sowie eine Funktion, mit der der Schlüssel für den Vergleich gesucht wird.
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)));
}
}
Sie können es so verwenden
list1.Exclude(list2, i => i.ID);
Sobald Sie einen generischen FuncEqualityComparer schreiben, können Sie ihn überall verwenden.
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);
}
Hier ein Arbeitsbeispiel, das IT-Kenntnisse vermittelt, über die ein Bewerber nicht verfügt.
//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);
extrahieren Sie zunächst IDs aus der Sammlung, wo die Bedingung gilt
List<int> indexes_Yes = this.Contenido.Where(x => x.key == 'TEST').Select(x => x.Id).ToList();
zweitens: Verwenden Sie "Compare", um die zur Auswahl unterschiedlichen IDs auszuwählen
List<int> indexes_No = this.Contenido.Where(x => !indexes_Yes.Contains(x.Id)).Select(x => x.Id).ToList();
Natürlich können Sie x.key! = "TEST" verwenden, ist aber nur ein Beispiel