web-dev-qa-db-fra.com

Requête LINQ pour rechercher si les éléments d'une liste sont contenus dans une autre liste

J'ai le code suivant:

List<string> test1 = new List<string> { "@bob.com", "@tom.com" };
List<string> test2 = new List<string> { "[email protected]", "[email protected]" };

Je dois supprimer toute personne dans test2 qui possède @ bob.com ou @ tom.com.

Ce que j'ai essayé, c'est ceci:

bool bContained1 = test1.Contains(test2);
bool bContained2 = test2.Contains(test1);

bContained1 = false mais bContained2 = true. Je préférerais ne pas parcourir chaque liste en boucle, mais utiliser une requête Linq pour récupérer les données. bContained1 est la même condition pour la requête Linq que j'ai créée ci-dessous:

List<string> test3 = test1.Where(w => !test2.Contains(w)).ToList();

La requête ci-dessus fonctionne avec une correspondance exacte mais pas avec des correspondances partielles.

J'ai examiné d'autres requêtes mais je peux trouver une comparaison étroite avec Linq. Toutes les idées ou n'importe où vous pouvez m'indiquer seraient d'une grande aide.

48
cjohns
var test2NotInTest1 = test2.Where(t2 => test1.Count(t1 => t2.Contains(t1))==0);

Version plus rapide selon la suggestion de Tim:

var test2NotInTest1 = test2.Where(t2 => !test1.Any(t1 => t2.Contains(t1)));
63
Giscard Biamby
var output = emails.Where(e => domains.All(d => !e.EndsWith(d)));

Ou si vous préférez:

var output = emails.Where(e => !domains.Any(d => e.EndsWith(d)));
11
Tim S.
bool doesL1ContainsL2 = l1.Intersect(l2).Count() == l2.Count;

L1 et L2 sont tous deux List<T>

7
Rohit Gupta

Pas besoin d'utiliser Linq comme ceci ici, car il existe déjà une méthode d'extension pour le faire pour vous.

Enumerable.Except<TSource>

http://msdn.Microsoft.com/en-us/library/bb336390.aspx

Vous avez juste besoin de créer votre propre comparateur pour comparer au besoin.

3
walther

quelque chose comme ça:

List<string> test1 = new List<string> { "@bob.com", "@tom.com" };
List<string> test2 = new List<string> { "[email protected]", "[email protected]" };

var res = test2.Where(f => test1.Count(z => f.Contains(z)) == 0)

Exemple en direct: ici

2
ren

Essayez ce qui suit:

List<string> test1 = new List<string> { "@bob.com", "@tom.com" };
List<string> test2 = new List<string> { "[email protected]", "[email protected]" };
var output = from goodEmails in test2
            where !(from email in test2
                from domain in test1
                where email.EndsWith(domain)
                select email).Contains(goodEmails)
            select goodEmails;

Cela fonctionne avec l'ensemble de test fourni (et semble correct).

0
Trisped
List<string> test1 = new List<string> { "@bob.com", "@tom.com" };
List<string> test2 = new List<string> { "[email protected]", "[email protected]", "[email protected]" };

var result = (from t2 in test2
              where test1.Any(t => t2.Contains(t)) == false
              select t2);

Si vous voulez utiliser le formulaire de requête, il est lisible et plus ou moins "performant", comme cela pourrait être.

Ce que je veux dire, c'est que ce que vous essayez de faire est un algorithme O (N * M), c’est-à-dire que vous devez traverser N éléments et les comparer à M valeurs. Ce que vous voulez, c'est parcourir la première liste une seule fois et la comparer à l'autre liste autant de fois que nécessaire (dans le pire des cas, le courrier électronique est valide puisqu'il doit être comparé à tous les domaines de la liste noire).

from t2 in test On boucle la liste de courriel une fois.

test1.Any(t => t2.Contains(t)) == false nous comparons avec la liste noire et lorsque nous avons trouvé un résultat correspondant (donc ne comparant pas avec la liste complète si ce n'est pas nécessaire)

select t2 Gardez ceux qui sont propres.

Donc, voici ce que je voudrais utiliser.

0
Francisco Soto