Frage LINQ-Abfrage, um zu ermitteln, ob Elemente in einer Liste in einer anderen Liste enthalten sind


Ich habe den folgenden Code:

List<string> test1 = new List<string> { "@bob.com", "@tom.com" };
List<string> test2 = new List<string> { "joe@bob.com", "test@sam.com" };

Ich muss jeden in test2 entfernen, der @ bob.com oder @ tom.com hat.

Was ich versucht habe, ist folgendes:

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

bContained1 = false aber bContained2 = true. Ich würde lieber nicht jede Liste durchlaufen, sondern stattdessen eine Linq-Abfrage verwenden, um die Daten abzurufen. bContained1 ist die gleiche Bedingung für die Linq-Abfrage, die ich unten erstellt habe:

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

Die obige Abfrage funktioniert mit einer genauen Übereinstimmung, aber nicht mit Teilübereinstimmungen.

Ich habe andere Abfragen angeschaut, aber ich kann einen ähnlichen Vergleich mit Linq finden. Irgendwelche Ideen oder irgendwo, wo Sie mich hinweisen können, wäre eine große Hilfe.


35
2017-09-29 21:21


Ursprung


Antworten:


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

Schnellere Version nach Tims Vorschlag:

var test2NotInTest1 = test2.Where(t2 => !test1.Any(t1 => t2.Contains(t1)));

46
2017-09-29 21:34



var output = emails.Where(e => domains.All(d => !e.EndsWith(d)));

Oder wenn Sie bevorzugen:

var output = emails.Where(e => !domains.Any(d => e.EndsWith(d)));

10
2017-09-29 21:39



Linq muss hier nicht verwendet werden, da es bereits eine Erweiterungsmethode für Sie gibt.

Enumerable.Except<TSource>

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

Sie müssen nur Ihren eigenen Vergleich erstellen, um ihn nach Bedarf zu vergleichen.


3
2017-09-29 21:32



bool doesL1ContainsL2 = l1.Intersect(l2).Count() == l2.Count;

L1 und L2 sind beide List<T>


3
2017-08-03 08:12



etwas wie das:

List<string> test1 = new List<string> { "@bob.com", "@tom.com" };
List<string> test2 = new List<string> { "joe@bob.com", "test@sam.com" };

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

Live-Beispiel: Hier


2
2017-09-29 21:37



Versuche Folgendes:

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

Dies funktioniert mit dem bereitgestellten Testset (und sieht korrekt aus).


0
2017-09-29 21:34



List<string> test1 = new List<string> { "@bob.com", "@tom.com" };
List<string> test2 = new List<string> { "joe@bob.com", "test@sam.com", "bets@tom.com" };

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

Wenn das Abfrageformular das ist, was Sie verwenden möchten, ist dies lesbar und mehr oder weniger so "performant" wie dies sein könnte.

Was ich meine, ist das, was Sie versuchen, ist ein O (N * M) Algorithmus, das heißt, Sie müssen N Elemente durchqueren und sie gegen M Werte vergleichen. Was Sie wollen, ist die erste Liste nur einmal durchqueren und vergleichen Sie mit der anderen Liste so oft wie nötig (schlimmsten Fall ist, wenn die E-Mail gültig ist, da es mit jeder schwarz gelisteten Domain vergleichen muss).

from t2 in test Wir führen die E-Mail-Liste einmal durch.

test1.Any(t => t2.Contains(t)) == false wir vergleichen mit der Blacklist und wenn wir eine Übereinstimmung gefunden haben (also nicht mit der ganzen Liste vergleichen, wenn sie nicht benötigt wird)

select t2 behalte die, die sauber sind.

Also das würde ich verwenden.


0
2017-09-29 21:40



List<string> l = new List<string> { "@bob.com", "@tom.com" };
List<string> l2 = new List<string> { "joe@bob.com", "test@bob.com" };
List<string> myboblist= (l2.Where (i=>i.Contains("bob")).ToList<string>());
foreach (var bob in myboblist)
    Console.WriteLine(bob.ToString());

-3
2018-02-28 15:52



Ich denke, das wäre am einfachsten:

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

-4
2018-01-04 15:54