Query LINQ per trovare se gli elementi in un elenco sono contenuti in un altro elenco

Ho il codice seguente:

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

Devo rimuovere chiunque in test2 che ha @ bob.com o @ tom.com.

Quello che ho provato è questo:

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

bContained1 = false ma bContained2 = true . Preferirei non eseguire il ciclo di ogni elenco ma utilizzare una query Linq per recuperare i dati. bContained1 è la stessa condizione per la query Linq che ho creato di seguito:

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

La query sopra funziona su una corrispondenza esatta ma non su corrispondenze parziali.

Ho esaminato altre query ma posso trovare un confronto ravvicinato con Linq. Qualsiasi idea o dovunque tu possa indicarmi sarebbe di grande aiuto.

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

Versione più veloce come da suggerimento di Tim:

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

O se preferisci:

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

L1 e L2 sono entrambi List

Non c’è bisogno di usare Linq come qui, perché esiste già un metodo di estensione per fare questo per te.

Enumerable.Except

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

Hai solo bisogno di creare il tuo comparatore per confrontare, se necessario.

qualcosa come questo:

 List test1 = new List { "@bob.com", "@tom.com" }; List test2 = new List { "[email protected]", "[email protected]" }; var res = test2.Where(f => test1.Count(z => f.Contains(z)) == 0) 

Esempio dal vivo: qui

Prova quanto segue:

 List test1 = new List { "@bob.com", "@tom.com" }; List test2 = new List { "[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; 

Funziona con il set di test fornito (e sembra corretto).

 List test1 = new List { "@bob.com", "@tom.com" }; List test2 = new List { "[email protected]", "[email protected]", "[email protected]" }; var result = (from t2 in test2 where test1.Any(t => t2.Contains(t)) == false select t2); 

Se il modulo di query è ciò che si desidera utilizzare, questo è leggibile e più o meno “performante” come potrebbe essere.

Quello che voglio dire è che quello che stai cercando di fare è un algoritmo O (N * M), cioè devi attraversare N elementi e confrontarli con i valori di M. Quello che vuoi è attraversare il primo elenco una sola volta e confrontarlo con l’altro elenco quante volte è necessario (il caso peggiore è quando l’email è valida poiché deve confrontarsi con ogni dominio elencato in nero).

from t2 in test facciamo un ciclo l’elenco e-mail una volta.

test1.Any(t => t2.Contains(t)) == false confrontiamo con la blacklist e quando abbiamo trovato un match return (quindi non confrontato con l’intero elenco se non è necessario)

select t2 mantieni quelli che sono puliti.

Quindi questo è quello che userei.

 List l = new List { "@bob.com", "@tom.com" }; List l2 = new List { "[email protected]", "[email protected]" }; List myboblist= (l2.Where (i=>i.Contains("bob")).ToList()); foreach (var bob in myboblist) Console.WriteLine(bob.ToString()); 

Penso che sarebbe più semplice:

 test1.ForEach(str => test2.RemoveAll(x=>x.Contains(str)));