2010-11-26 59 views

回答

29

選擇很多,您可以選擇從是一個IEnumerable <牛逼>收集查詢源的屬性,但而不是返回集合的集合(IEnumerable的< IEnumerable的<牛逼> >)將集合壓扁成一個單一的採集。

這裏,您可以運行演示和選擇的SelectMany之間的差異的例子:

//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); 

通過使用你的SelectMany使其更易於孩子集合中查詢值。

+0

感謝abatishchev,我還沒有發現這個錯誤。 – 2010-11-26 10:10:56

6

的SelectMany基本上變平並處理分層數據,並且具有兩種主要形式

(對實施例的目的,請參見該初始代碼)

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"}); 

選項1)從集合創建一個集合集合(基本上平坦分層數據)

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

結果是:

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

選項2)從集合的集合創建一個集合,然後通過與原始親本的基準處理所述新集合中的每個項目

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

結果是:

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

上述每個用途都有一個變體,其中正在處理的項目的索引可用於變換函數。

3

我使用此擴展名全部潛入層次結構的時間。

另一個很酷的方式做到這一點,當擴展變得有點凌亂就是用正規的LINQ方式,如:

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

這將是等效的:

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

這可在添加where子句和連接時得到一點點冗長等。 希望這有助於!

0

我在LINQ中使用SelectMany有一些樂趣。下面的鏈接描述了返回一個在LINQ select子句中的IEnumerable,它返回一系列序列,並使用SelectMany將它平鋪爲一個簡單的序列。 "Linq to XML using Let, Yield return and Selectmany"。 這不僅僅是一個SelectMany用例,而是一種從LINQ中的單個輸入生成多個輸出的方法的一部分。

13

SelectMany有幾個過載。其中之一允許您在遍歷層次結構時跟蹤父級和子級之間的任何關係。

:假設你有以下結構:League -> Teams -> Player

您可以輕鬆地返回球員平坦的集合。然而,你可能會失去任何球員參與的球隊的參考。

幸運的是有這樣的目的的過載:

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 
            }; 

前面的例子是從丹的IK博客採取:

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

強烈建議您先看看它。

0

這裏是另一個(VB.NET)使用示例:

'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