Je suppose qu'il existe une simple requête LINQ pour le faire, je ne sais pas exactement comment. S'il vous plaît voir l'extrait de code ci-dessous.
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; }
}
Je voudrais effectuer une requête LINQ pour me donner toutes les personnes dans peopleList2
qui ne sont pas dans peopleList1
cet exemple devrait me donner deux personnes (ID = 4 & ID = 5)
var result = peopleList2.Where(p => !peopleList1.Any(p2 => p2.ID == p.ID));
Si vous substituez l'égalité des personnes, vous pouvez également utiliser:
peopleList2.Except(peopleList1)
Except
devrait être nettement plus rapide que la variante Where(...Any)
car elle peut placer la deuxième liste dans une table de hachage. Where(...Any)
a une durée d'exécution de O(peopleList1.Count * peopleList2.Count)
alors que les variantes basées sur HashSet<T>
(presque) ont une durée d'exécution de O(peopleList1.Count + peopleList2.Count)
.
Except
supprime implicitement les doublons. Cela ne devrait pas affecter votre cas, mais pourrait être un problème pour des cas similaires.
Ou si vous voulez un code rapide mais que vous ne voulez pas remplacer l'égalité:
var excludedIDs = new HashSet<int>(peopleList1.Select(p => p.ID));
var result = peopleList2.Where(p => !excludedIDs.Contains(p.ID));
Cette variante ne supprime pas les doublons.
Ou si vous le voulez sans négation:
var result = peopleList2.Where(p => peopleList1.All(p2 => p2.ID != p.ID));
Fondamentalement, il est dit que tout doit être extrait de peopleList2 où tous les identifiants de peopleList1 sont différents de id de peoplesList2.
Juste une approche un peu différente de la réponse acceptée :)
Comme toutes les solutions utilisées à ce jour utilisaient une syntaxe fluide, voici une solution de syntaxe d'expression de requête destinée aux personnes intéressées:
var peopleDifference =
from person2 in peopleList2
where !(
from person1 in peopleList1
select person1.ID
).Contains(person2.ID)
select person2;
Je pense que cela est suffisamment différent des réponses données pour intéresser certains, même si cela serait probablement très optimiste pour les listes. Maintenant, pour les tables avec des ID indexés, ce serait vraiment la voie à suivre.
Un peu en retard pour le parti mais une bonne solution qui est également compatible Linq to SQL est:
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>();
Félicitations à http://www.dotnet-tricks.com/Tutorial/linq/UXPF181012-SQL-Joins-with-C
Cette extension énumérable vous permet de définir une liste d'éléments à exclure et une fonction à utiliser pour rechercher la clé à utiliser pour effectuer une comparaison.
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)));
}
}
Vous pouvez l'utiliser de cette façon
list1.Exclude(list2, i => i.ID);
Une fois que vous avez écrit un FuncEqualityComparer générique, vous pouvez l’utiliser partout.
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);
}
Voici un exemple de travail qui permet d’acquérir des compétences en informatique qu’un candidat à un poste ne possède pas déjà.
//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);
d’abord, extrayez les identifiants de la collection où condition
List<int> indexes_Yes = this.Contenido.Where(x => x.key == 'TEST').Select(x => x.Id).ToList();
deuxièmement, utilisez le paramètre "compare" pour sélectionner des identifiants différents de ceux sélectionnés
List<int> indexes_No = this.Contenido.Where(x => !indexes_Yes.Contains(x.Id)).Select(x => x.Id).ToList();
Évidemment, vous pouvez utiliser x.key! = "TEST", mais ce n’est qu’un exemple.