Zakładam, że jest to proste zapytanie LINQ, ale nie jestem pewien, jak to zrobić.
Biorąc pod uwagę ten fragment kodu:
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; }
}
Chciałbym wykonać zapytanie LINQ, aby dać mi wszystkie osoby peopleList2
, których nie ma peopleList1
.
Ten przykład powinien dać mi dwie osoby (ID = 4 i ID = 5)
Odpowiedzi:
Można to rozwiązać za pomocą następującego wyrażenia LINQ:
Alternatywny sposób wyrażenia tego za pomocą LINQ, który niektórzy programiści uważają za bardziej czytelny:
źródło
Jeśli zastąpisz równość osób, możesz również użyć:
Except
powinien być znacznie szybszy niżWhere(...Any)
wariant, ponieważ może umieścić drugą listę w tablicy mieszającej.Where(...Any)
ma czas działania,O(peopleList1.Count * peopleList2.Count)
podczas gdy warianty oparte naHashSet<T>
(prawie) mają czas działaniaO(peopleList1.Count + peopleList2.Count)
.Except
niejawnie usuwa duplikaty. Nie powinno to mieć wpływu na twoją sprawę, ale może być problemem w podobnych przypadkach.Lub jeśli chcesz szybkiego kodu, ale nie chcesz nadpisywać równości:
Ten wariant nie usuwa duplikatów.
źródło
Equals
zostało zastąpione w celu porównania identyfikatorów.Lub jeśli chcesz to bez negacji:
Zasadniczo mówi get get from peopleList2, gdzie wszystkie identyfikatory w peopleList1 różnią się od identyfikatora w peoplesList2.
Tylko trochę inne podejście od przyjętej odpowiedzi :)
źródło
Ponieważ wszystkie dotychczasowe rozwiązania wykorzystywały płynną składnię, oto rozwiązanie w składni wyrażeń zapytań dla zainteresowanych:
Myślę, że jest wystarczająco różny od udzielonych odpowiedzi, aby zainteresować niektórych, nawet sądziłem, że prawdopodobnie nie będzie optymalny dla List. Teraz, jeśli chodzi o tabele z indeksowanymi identyfikatorami, zdecydowanie byłby to właściwy sposób.
źródło
Trochę za późno na imprezę, ale dobrym rozwiązaniem, które jest również zgodne z Linq na SQL, jest:
Wyrazy uznania dla http://www.dotnet-tricks.com/Tutorial/linq/UXPF181012-SQL-Joins-with-C
źródło
Odpowiedź Klausa była świetna, ale ReSharper poprosi cię o „Uprość wyrażenie LINQ”:
var result = peopleList2.Where(p => peopleList1.All(p2 => p2.ID != p.ID));
źródło
To Enumerable Extension pozwala zdefiniować listę elementów do wykluczenia oraz funkcję, która ma zostać użyta do znalezienia klucza do wykonania porównania.
Możesz użyć tego w ten sposób
źródło
Oto działający przykład, który pozwala zdobyć umiejętności informatyczne, których kandydat do pracy jeszcze nie posiada.
źródło
najpierw wyodrębnij identyfikatory z kolekcji, w której warunek
po drugie, użyj wartości „porównaj”, aby wybrać identyfikatory różne od wyboru
Oczywiście możesz użyć x.key! = "TEST", ale to tylko przykład
źródło
Po napisaniu ogólnego FuncEqualityComparer możesz go używać wszędzie.
źródło