2011-01-10 2 views
1

私の頭脳のためにリニューアルされた以下のリグはあまりにもジェダイですが、私は可能なことをやろうとしていますか?Linq複数のテーブルで区別できますか?

var aa = new string[] { "1", "2" }; 
var bb = new string[] { "1", "2", "3" }; 
var cc = new string[] { "2" }; 

//*cannot directly reference the above anymore*// 
var dd = new string[][] { aa, bb, cc }; 
//result = dd.**magical linq to only get item(s) present in each table** i.e. result = {"2"} 
+0

「magical linq」を読むと、私は実際に笑いました。 – Kredns

答えて

3
var result = dd.Aggregate<IEnumerable<string>>((a, x) => a.Intersect(x)); 

あなたは少し良い理論的なパフォーマンスをしたい場合は、いくつかの読みやすさを犠牲にし、その後、代わりに以下のことができます。それは、明示的なHashSet<T>を使用して、結果を次の反復に平文IEnumerable<T>ではなく渡すために、各交差操作に対して新しいセットを構築する必要性を回避します。

var result = dd.Aggregate((HashSet<string>)null, 
          (a, x) => { 
             if (a == null) 
              a = new HashSet<string>(x); 
             else 
              a.IntersectWith(x); 
             return a; 
            }); 
+0

なぜこれは、例えば、ジョインよりも効果的です...私にとっては、ジョインを使用する必要があるようです。私の遅い答えを見てください...しかし、それは 'Aggregate'と素晴らしい解決策です:)。 –

+0

-1、Linqプロバイダを効率的に動作させるのではなく、すべての結果処理をCLRオブジェクトにプッシュします。これは正解({"2"})を与えてくれますか? – RichardW1001

+0

@リチャード:これがLINQ-to-Objectsの場合、質問の例は確かに 'string [] []'配列のデータソースです。* LINQプロバイダを効率的に使用しています。そして、実際にあなたが正しい答えを出すかどうかを調べて、あなたの疑念ではなく事実にあなたの下垂体を置くのを見てみませんか? – LukeH

3

ありniftier方法かもしれないが、あなたは、ループ内でクエリを作成することができます

var aa = new string[] { "1", "2" }; 
var bb = new string[] { "1", "2", "3" }; 
var cc = new string[] { "2" }; 

var dd=new string[][] { aa, bb, cc }; 

IEnumerable<string> q=dd.First(); 

for(var i=1;i<dd.Length;++i) 
{ 
    q=q.Intersect(dd[i]); 
} 
+0

Linqの要点はループを避けることですか? – RichardW1001

+0

@リチャード:LINQの全ポイントはループを避けるものではありません。コードをより表現力豊かで読みやすいものにすることです。プレーンループがLINQ同等物よりも読みやすくなることがよくあります。 – LukeH

+0

はい、いいえ、可読性は重要ですが、多くの場合、Linqは基本的なLinqプロバイダの仕組みによって異なった動作をし、ループを実行することでその機能を削除します。最も目に見える例は、式がSQLに変換されてデータベース上で実行されるSQLプロバイダです。ループを実行すると、パフォーマンス・コストがかかるステージをバイパスします。 – RichardW1001

3

あなたは、集合演算子を使用することができます - UNION、INTERSECTなど

(編集 - 誤読質問!)

私が交差あなたはボックスの外にまっすぐ後にしているものをあなたに与えます信じています:

var dd = aa.Intersect(bb).Intersect(cc); 

これは、aa bbとccがすでに同じタイプのすべてのIEnumerableであるために機能することに注意してください。あなたがたToArray()、ToListメソッドの連鎖ができたので、のIQueryableがあるでしょう

var dd = aa.Select(a => a.PropertyA).Intersect(bb.Select(b => b.PropertyB).Intersect(cc.Select(c => c.PropertyC); 

結果:あなたのIEnumerablesは(別のLINQのテーブルからのような)異なるタイプである場合、あなたがしたいプロパティを投影する必要があります()などを使用して結果を返します。

0

なぜ単純結合を使用しないのですか?

class Program 
{ 
    static void Main(string[] args) 
    { 
     var aa = new string[] { "1", "2", "4" }; 
     var bb = new string[] { "1", "2", "3", "4" }; 
     var cc = new string[] { "2", "4" }; 

     //*cannot directly reference the above anymore*// 
     var dd = new string[][] { aa, bb, cc }; 

     var result = dd.Aggregate((x, y) => x.Join(y, z => z, z => z, (z, v) => z).ToArray()); 
     foreach (var item in result) 
     { 
      Console.WriteLine(item); 
     } 
     Console.ReadLine(); 
    } 
} 
3

注意、あなたはSQLにLINQを使用していて、IEnumerableを<に複合照会の任意の部分をキャストする場合>、その部分は、単一のSQLクエリを形成するために、クエリの残りの部分と組み合わせることはできません。この例では、クエリーが暗黙的にIEnumerable <>にキャストされ、 'q'に割り当てられている場合、この例のデータソースとしてSQLを使用しています。代わりにIQueryableを使用してください。各IEnumerableは遅延されていますが、3つのSQLクエリがサーバーに送信され、交差はメモリ内で実行されます。

参照を取得するには、Returning IEnumerable<T> vs. IQueryable<T>を参照するか、「IEnumerable vs IQueryable」を検索してください。

関連する問題