Angenommen, ich habe eine beliebige Anzahl von Sammlungen, die jeweils Objekte desselben Typs enthalten (z. B. List<int> foo
und List<int> bar
). Wenn diese Sammlungen selbst in einer Sammlung wären (z. B. vom Typ List<List<int>>
, könnte ich SelectMany
sie alle zu einer Sammlung kombinieren.
Wenn sich diese Sammlungen jedoch nicht bereits in derselben Sammlung befinden, hätte ich den Eindruck, dass ich eine Methode wie diese schreiben müsste:
public static IEnumerable<T> Combine<T>(params ICollection<T>[] toCombine)
{
return toCombine.SelectMany(x => x);
}
Was ich dann so nennen würde:
var combined = Combine(foo, bar);
Gibt es eine saubere und elegante Möglichkeit, (beliebig viele) Sammlungen zu kombinieren, ohne eine Dienstprogrammmethode wie Combine
oben schreiben zu müssen ? Es scheint einfach genug, dass es eine Möglichkeit geben sollte, dies in LINQ zu tun, aber vielleicht auch nicht.
c#
linq
generics
collections
Krapfen
quelle
quelle
Antworten:
Ich denke, Sie suchen vielleicht nach LINQs
.Concat()
?Alternativ
.Union()
werden doppelte Elemente entfernt.quelle
.Union()
Tipp. Denken Sie daran, dass Sie IComparer auf Ihrem benutzerdefinierten Typ implementieren müssen , falls dies der Fall ist.Für mich ist
Concat
eine Erweiterungsmethode in meinem Code nicht sehr elegant, wenn ich mehrere große Sequenzen zu konkatieren habe. Dies ist lediglich ein Codde-Einrückungs- / Formatierungsproblem und etwas sehr Persönliches.Sicher sieht es so gut aus:
Nicht so lesbar, wenn es lautet wie:
Oder wenn es so aussieht:
oder was auch immer Ihre bevorzugte Formatierung ist. Bei komplexeren Konkaten wird es noch schlimmer. Der Grund für meine Art von kognitiver Dissonanz mit dem obigen Stil ist, dass die erste Sequenz außerhalb der
Concat
Methode liegt, während die nachfolgenden Sequenzen innerhalb liegen. Ich rufe lieber die statischeConcat
Methode direkt auf und nicht den Erweiterungsstil:Für mehr Anzahl von Konkaten von Sequenzen verwende ich die gleiche statische Methode wie in OP:
So kann ich schreiben:
Sieht besser aus. Der zusätzliche, ansonsten redundante Klassenname, den ich schreiben muss, ist für mich kein Problem, da meine Sequenzen mit dem
Concat
Aufruf sauberer aussehen . In C # 6 ist das weniger problematisch . Sie können einfach schreiben:Ich wünschte, wir hätten Listenverkettungsoperatoren in C #, so etwas wie:
So viel sauberer.
quelle
Where
,OrderBy
) zunächst für Klarheit, vor allem , wenn sie sind etwas komplexer als dieses Beispiel.Für den Fall , wenn Sie tun eine Sammlung von Sammlungen, dh ein
List<List<T>>
,Enumerable.Aggregate
ist ein eleganter Weg , um alle Listen zu einem kombinieren:quelle
lists
zuerst hierher? Das ist das erste Problem, das OP hat. Wenn er am Anfang einen hattecollection<collection>
, dannSelectMany
ist es einfach viel einfacher.Verwenden Sie
Enumerable.Concat
wie folgt:quelle
Verwendung
Enumerable.Concact
:quelle
Sie können Aggregate immer in Kombination mit Concat ...
quelle
SelectMany
ist einfach einfacher.Der einzige Weg, den ich sehe, ist zu verwenden
Concat()
Aber Sie sollten entscheiden, was besser ist:
oder
Ein Punkt, warum
Concat()
eine bessere Wahl sein wird, ist, dass es für einen anderen Entwickler offensichtlicher sein wird. Lesbarer und einfacher.quelle
Sie können Union wie folgt verwenden:
Dadurch werden jedoch identische Elemente entfernt. Wenn Sie diese haben, möchten Sie möglicherweise
Concat
stattdessen verwenden.quelle
Enumerable.Union
ist eine Mengenvereinigung, die nicht das gewünschte Ergebnis liefert (sie liefert nur einmal Duplikate).int
in meinem Beispiel hätte die Leute ein wenig abschrecken können. aberUnion
für mich in diesem Fall nicht funktionieren.Ein paar Techniken mit Collection Initializers -
unter der Annahme dieser Listen:
SelectMany
mit einem Array-Initialisierer (für mich nicht wirklich so elegant, aber auf keine Hilfsfunktion angewiesen):Definieren Sie eine Listenerweiterung für Hinzufügen, die
IEnumerable<T>
imList<T>
Initialisierer Folgendes zulässt :Anschließend können Sie eine neue Liste erstellen, die die Elemente der anderen enthält (dies ermöglicht auch das Einmischen einzelner Elemente).
quelle
Angesichts der Tatsache, dass Sie mit einer Reihe separater Sammlungen beginnen, finde ich Ihre Lösung ziemlich elegant. Sie müssen etwas tun , um sie zusammenzunähen.
Syntaktisch wäre es bequemer, aus Ihrer Combine-Methode eine Erweiterungsmethode zu machen, die sie überall verfügbar macht.
quelle
Alles was Sie brauchen ist Folgendes
IEnumerable<IEnumerable<T>> lists
:Dadurch werden alle Elemente
lists
zu einem zusammengefasstIEnumerable<T>
(mit Duplikaten). Verwenden SieUnion
stattConcat
, um Duplikate zu entfernen, wie in den anderen Antworten angegeben.quelle