2010-11-26 20 views

Antwort

29

viele Wählen können Sie eine Eigenschaft aus der Abfrage Quelle auszuwählen, die eine IEnumerable <T> Sammlung, sondern eine Sammlung von Sammlungen der Rückkehr (IEnumerable < IEnumerable <T> >) wird es die Sammlungen in einem einzigen abflachen Sammlung.

Hier ist ein Beispiel, das die Unterschiede zwischen Select und Select demonstrieren ausführen können:

//set up some data for our example 
var tuple1 = new { Name = "Tuple1", Values = new int [] { 1, 2, 3 } }; 
var tuple2 = new { Name = "Tuple2", Values = new int [] { 4, 5, 6 } }; 
var tuple3 = new { Name = "Tuple3", Values = new int [] { 7, 8, 9 } }; 

//put the tuples into a collection 
var tuples = new [] { tuple1, tuple2, tuple3 }; 

//"tupleValues" is an IEnumerable<IEnumerable<int>> that contains { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } } 
var tupleValues = tuples.Select(t => t.Values); 

//"tupleSelectManyValues" is an IEnumerable<int> that contains { 1, 2, 3, 4, 5, 6, 7, 8, 9 } 
var tupleSelectManyValues = tuples.SelectMany(t => t.Values); 

Durch die Verwendung von Select Sie es einfacher abfragen Werte innerhalb Kind Sammlungen.

+0

Dank abatishchev, ich hatte den Tippfehler nicht entdeckt. –

6

Select flacht grundsätzlich und verarbeitet hierarchische Daten, und hat zwei Hauptformen

(für die Zwecke der Beispiele finden Sie in diesem Anfangscode)

class TestObj 
{ 
    public string Name { get; set; } 
    public List<string> Items { get; set; } 
} 

var hierarchicalCollection = new List<TestObj>(); 

hierarchicalCollection.Add(new TestObj() 
    {Items = new List<string>() 
     {"testObj1-Item1", "testObj1-Item2"}, Name="t1"}); 
hierarchicalCollection.Add(new TestObj() 
    {Items = new List<string>() 
     {"testObj2-Item1", "testObj2-Item2"}, Name="t2"}); 

Option 1) erzeugt eine Sammlung aus einer Sammlung von Sammlungen (im wesentlichen hierarchischen Daten Abflachen)

IEnumerable<string> flattenedCollection = 
    hierarchicalCollection.SelectMany(t => t.Items); 

Das Ergebnis ist:

"testObj1-Item1" 
"testObj1-Item2" 
"testObj2-Item1" 
"testObj2-Item2" 

Option 2) erstellt eine Sammlung aus einer Sammlung von Sammlungen und verarbeitet dann jedes Element der neuen Kollektion über einen Verweis auf die ursprüngliche Mutter

IEnumerable<string> flattenedModifiedCollection = 
    hierarchicalCollection.SelectMany 
     (t => t.Items, (t, i) => t.Name + " : " + i); 

das Ergebnis:

"t1 : testObj1-Item1" 
"t1 : testObj1-Item2" 
"t2 : testObj2-Item1" 
"t2 : testObj2-Item2" 

Jede der obigen Verwendungsarten hat eine Variante, bei der der Index des zu verarbeitenden Elements den Transformationsfunktionen zur Verfügung steht.

3

Ich benutze diese Erweiterung alle die Zeit für das Tauchen in Hierarchien.

andere kühle Art und Weise, dies zu tun, wenn die Erweiterungen ein bisschen chaotisch ist die formale LINQ Weise zu verwenden, wie:

var vehicles = context.Customers.SelectMany(c => c.Fleets).SelectMany(f => f.Vehicles); 

Dies kann

:

var vehicles = from cust in context.Customers 
       from fleet in cust.Fleets 
       from v in fleet.Vehicles 
       select v; 

Dies wäre das Äquivalent sein Beim Hinzufügen von Where-Klauseln und Joins etc. ein bisschen langatmig werden. Hoffe, das hilft!

0

Ich hatte etwas Spaß mit SelectMany in LINQ. Der folgende Link beschreibt die Rückgabe eines IEnumerable in einer LINQ SELECT-Klausel, die eine Sequenz von Sequenzen zurückgibt und SelectMany verwendet, um diese in eine einfache Sequenz umzuwandeln. "Linq to XML using Let, Yield return and Selectmany". Es ist nicht nur ein SelectMany-Anwendungsfall, sondern Teil eines Ansatzes, der mehrere Ausgaben von einer einzelnen Eingabe in LINQ generiert.

13

Es gibt mehrere Überladungen zu SelectMany. Einer von ihnen ermöglicht Ihnen, die Beziehung zwischen Eltern und Kindern zu verfolgen, während Sie die Hierarchie durchlaufen.

Beispiel: Angenommen, Sie die folgende Struktur haben: League -> Teams -> Player

Sie können eine flache Sammlung von Spielern leicht zurück. Sie können jedoch jegliche Bezugnahme auf das Team verlieren, zu dem ein Spieler gehört.

Glücklicherweise gibt es eine Überlastung für einen solchen Zweck:

var teamsAndTheirLeagues = 
     from helper in leagues.SelectMany 
       (l => l.Teams 
       , (league, team) => new { league, team }) 
         where helper.team.Players.Count > 2 
          && helper.league.Teams.Count < 10 
          select new 
            { LeagueID = helper.league.ID 
            , Team = helper.team 
            }; 

Das vorherige Beispiel von Dans IK Blog genommen wird:

http://blogs.interknowlogy.com/2008/10/10/use-linqs-selectmany-method-to-flatten-collections/

I stark empfehlen Sie es einen Blick . Hier

0

ist ein anderes (VB.NET) Verwendungsbeispiel:

'Original list 
Dim l() As String = {"/d", "/bc:\Temp\In*;c:\Temp\Out", "/hABC", "/s123"} 

'Processed list: will list first 2 characters from each string member. 
Dim L1 As IEnumerable(Of String) = l.SelectMany(Function(x As String) {x.Substring(0, 2)}) 

Dim L2 As List(Of String) = l.SelectMany(Function(x As String) {x.Substring(0, 2)}).ToList 

'Will return dictionary like list with keys==2 characters and values the rest from each string member. 
Dim L3 As List(Of KeyValuePair(Of String, String)) = l.SelectMany(Function(x As String) {New KeyValuePair(Of String, String)(x.Substring(0, 2), x.Substring(2))}).ToList 
Verwandte Themen