2010-11-26 11 views

答えて

29

多くは、それが単一にコレクションを平らにします(> > IEnumerableを<のIEnumerable < T)、あなたがIEnumerableを<T>コレクションですクエリのソースからプロパティを選択することができますが、代わりに、コレクションのコレクションを返すの選択コレクション。ここで

は、あなたが選択し、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、私はタイプミスを発見していませんでした。 –

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

私はこのエクステンションを使用しますすべて階層にダイビングする時間。

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

これができます。

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

これは同等の次のようになります。

拡張機能は少し厄介取得するときにこれを行うためのもう一つのクールな方法は次のように、正式なLINQの方法を使用することですどこに句や結合などを追加するときに少し長い風になる これは助けて欲しい!

0

LINQでSelectManyを使用して楽しい経験をしています。次のリンクでは、シーケンスのシーケンスを返すLINQのselect句にIEnumerableを返し、SelectManyを使用して単純なシーケンスに展開します。 "Linq to XML using Let, Yield return and Selectmany"。 これは単なるSelectManyの使用例ではありませんが、LINQの単一入力から複数の出力を生成する手法の一部です。

13

SelectManyにいくつかのオーバーロードがあります。それらのうちの1つを使用すると、階層を横切って親と子の間の関係を追跡することができます。

League -> Teams -> Player

あなたが簡単に選手の平らなコレクションを返すことができます:あなたは次のような構造を持っていると仮定します。しかし、あなたがプレイヤーの一部であるチームへの参照を失う可能性があります。前の例では、ダンのIKのブログから取られ

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

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