Mengenvorgänge (C#)

Mengenvorgänge in LINQ sind Abfrageoperationen, die ein Resultset erzeugen, das auf dem Vorhandensein oder Fehlen äquivalenter Elemente in derselben oder in einer anderen Auflistung basiert.

Methodennamen BESCHREIBUNG C#-Abfrageausdruckssyntax Weitere Informationen
Distinct oder DistinctBy Entfernt doppelte Werte aus einer Auflistung Nicht zutreffend. Enumerable.Distinct
Enumerable.DistinctBy
Queryable.Distinct
Queryable.DistinctBy
Except oder ExceptBy Gibt die Unterschiedsmenge zurück, das heißt die Elemente einer Auflistung, die in einer zweiten Auflistung nicht vorkommen. Nicht zutreffend. Enumerable.Except
Enumerable.ExceptBy
Queryable.Except
Queryable.ExceptBy
Intersect oder IntersectBy Gibt die Schnittmenge zurück, d.h. die Elemente, die in beiden Auflistungen angezeigt werden Nicht zutreffend. Enumerable.Intersect
Enumerable.IntersectBy
Queryable.Intersect
Queryable.IntersectBy
Union oder UnionBy Gibt die Vereinigungsmenge zurück, d.h. eindeutige Elemente, die in einer der beiden Auflistungen angezeigt werden Nicht zutreffend. Enumerable.Union
Enumerable.UnionBy
Queryable.Union
Queryable.UnionBy

Distinct und DistinctBy

Das folgende Beispiel veranschaulicht das Verhalten der Enumerable.Distinct-Methode in einer Sequenz aus Zeichenfolgen. Die zurückgegebene Sequenz enthält die eindeutigen Elemente aus der Eingabesequenz.

Graphic showing the behavior of Distinct()

string[] words = ["the", "quick", "brown", "fox", "jumped", "over", "the", "lazy", "dog"];

IEnumerable<string> query = from word in words.Distinct()
                            select word;

foreach (var str in query)
{
    Console.WriteLine(str);
}

/* This code produces the following output:
 *
 * the
 * quick
 * brown
 * fox
 * jumped
 * over
 * lazy
 * dog
 */

DistinctBy ist ein alternativer Ansatz für die Distinct-Methode, die ein keySelector-Element akzeptiert. Der keySelector wird als Vergleichsdiskriminator des Quelltyps verwendet. Im folgenden Code werden Wörter basierend auf ihrer Lengthunterteilt. Das jeweils erste Wort jeder Länge wird angezeigt:

string[] words = ["the", "quick", "brown", "fox", "jumped", "over", "the", "lazy", "dog"];

foreach (string word in words.DistinctBy(p => p.Length))
{
    Console.WriteLine(word);
}

// This code produces the following output:
//     the
//     quick
//     jumped
//     over

Except und ExceptBy

Im folgenden Beispiel wird das Verhalten von Enumerable.Except veranschaulicht. Die zurückgegebene Sequenz enthält nur die Elemente aus der ersten Eingabesequenz, die nicht in der zweiten Eingabesequenz vorkommen.

Graphic showing the action of Except()

In den folgenden Beispielen in diesem Artikel werden die allgemeinen Datenquellen für diesen Bereich verwendet:

public enum GradeLevel
{
    FirstYear = 1,
    SecondYear,
    ThirdYear,
    FourthYear
};

public class Student
{
    public required string FirstName { get; init; }
    public required string LastName { get; init; }
    public required int ID { get; init; }

    public required GradeLevel Year { get; init; }
    public required List<int> Scores { get; init; }

    public required int DepartmentID { get; init; }
}

public class Teacher
{
    public required string First { get; init; }
    public required string Last { get; init; }
    public required int ID { get; init; }
    public required string City { get; init; }
}
public class Department
{
    public required string Name { get; init; }
    public int ID { get; init; }

    public required int TeacherID { get; init; }
}

Allen Student sind eine Klassenstufe, ein primärer Fachbereich und mehrere Bewertungen zugeordnet. Teacher verfügen auch über eine City-Eigenschaft, die den Campus identifiziert, auf dem die Lehrkraft unterrichtet. Eine Department hat einen Namen und einen Verweis auf eine Teacher, die den Fachbereich leitet.

string[] words1 = ["the", "quick", "brown", "fox"];
string[] words2 = ["jumped", "over", "the", "lazy", "dog"];

IEnumerable<string> query = from word in words1.Except(words2)
                            select word;

foreach (var str in query)
{
    Console.WriteLine(str);
}

/* This code produces the following output:
 *
 * quick
 * brown
 * fox
 */

Die ExceptBy-Methode ist ein alternativer Ansatz für die Except-Methode, die zwei Sequenzen möglicherweise heterogener Typen und ein keySelector-Element akzeptiert. Der keySelector hat denselben Typ wie die erste Auflistung. Betrachten Sie das folgenden Teacher-Array und die Lehrkraft-IDs, die ausgeschlossen werden sollen. Um Lehrkräfte in der ersten Auflistung zu finden, die nicht in der zweiten Sammlung enthalten sind, können Sie die Lehrkraft-ID auf die zweite Auflistung projizieren:

int[] teachersToExclude =
[
    901,    // English
    965,    // Mathematics
    932,    // Engineering
    945,    // Economics
    987,    // Physics
    901     // Chemistry
];

foreach (Teacher teacher in
    teachers.ExceptBy(
        teachersToExclude, teacher => teacher.ID))
{
    Console.WriteLine($"{teacher.First} {teacher.Last}");
}

Im oben stehenden C#-Code ist Folgendes passiert:

  • Das teachers-Array wird nur nach den Lehrkräften gefiltert, die nicht im teachersToExclude-Array enthalten sind.
  • Das teachersToExclude-Array enthält den ID-Wert für alle Lehrkräfte, die einen Fachbereich leiten.
  • Der Aufruf von ExceptBy ergibt eine neue Gruppe von Werten, die auf die Konsole geschrieben werden.

Der neue Wertesatz ist vom Typ Teacher, und das ist der Typ der ersten Auflistung. Jedes teacher-Element im teachers-Array, das keinen entsprechenden ID-Wert im teachersToExclude-Array besitzt, wird an der Konsole ausgegeben.

Intersect und IntersectBy

Im folgenden Beispiel wird das Verhalten von Enumerable.Intersect veranschaulicht. Die zurückgegebene Sequenz enthält die Elemente, die in beiden Eingabesequenzen verwendet werden.

Graphic showing the intersection of two sequences

string[] words1 = ["the", "quick", "brown", "fox"];
string[] words2 = ["jumped", "over", "the", "lazy", "dog"];

IEnumerable<string> query = from word in words1.Intersect(words2)
                            select word;

foreach (var str in query)
{
    Console.WriteLine(str);
}

/* This code produces the following output:
 *
 * the
 */

Die IntersectBy-Methode ist ein alternativer Ansatz für die Intersect-Methode, die zwei Sequenzen möglicherweise heterogener Typen und ein keySelector-Element akzeptiert. Der keySelector wird als Vergleichsdiskriminator des Typs der zweiten Auflistung verwendet. Betrachten Sie die folgenden Arrays mit Lernenden und Lehrkräften. Die Abfrage gleicht Elemente in jeder Sequenz anhand des Namens ab, um die Lernenden zu finden, die nicht auch Lehrkräfte sind:

foreach (Student person in
    students.IntersectBy(
        teachers.Select(t => (t.First, t.Last)), s => (s.FirstName, s.LastName)))
{
    Console.WriteLine($"{person.FirstName} {person.LastName}");
}

Im oben stehenden C#-Code ist Folgendes passiert:

  • Die Abfrage erzeugt die Schnittmenge von Teacher und Student durch einen Vergleich der Namen.
  • Nur Personen, die sich in beiden Arrays finden, sind in der resultierenden Sequenz vorhanden.
  • Die resultierenden Student-Instanzen werden an die Konsole ausgegeben.

Union und UnionBy

Das folgende Beispiel veranschaulicht einen Vereinigungsvorgang zweier Sequenzen aus Zeichenfolgen. Die zurückgegebene Sequenz enthält die eindeutigen Elemente aus beiden Eingabesequenzen.

Graphic showing the union of two sequences.

string[] words1 = ["the", "quick", "brown", "fox"];
string[] words2 = ["jumped", "over", "the", "lazy", "dog"];

IEnumerable<string> query = from word in words1.Union(words2)
                            select word;

foreach (var str in query)
{
    Console.WriteLine(str);
}

/* This code produces the following output:
 *
 * the
 * quick
 * brown
 * fox
 * jumped
 * over
 * lazy
 * dog
*/

Die UnionBy-Methode ist ein alternativer Ansatz für die Union-Methode, die zwei Sequenzen desselben Typs und ein keySelector-Element akzeptiert. Der keySelector wird als Vergleichsdiskriminator des Quelltyps verwendet. Die folgende Abfrage erzeugt die Liste aller Personen, die entweder Lernende oder Lehrkräfte sind. Lernende, die auch Lehrkräfte sind, werden der Vereinigung nur einmal hinzugefügt:

foreach (var person in
    students.Select(s => (s.FirstName, s.LastName)).UnionBy(
        teachers.Select(t => (FirstName: t.First, LastName: t.Last)), s => (s.FirstName, s.LastName)))
{
    Console.WriteLine($"{person.FirstName} {person.LastName}");
}

Im oben stehenden C#-Code ist Folgendes passiert:

  • Die Arrays teachers und students werden anhand der Namen als Schlüsselselektor vereinigt.
  • Die resultierenden Namen werden an der Konsole ausgegeben.

Siehe auch