web-dev-qa-db-ja.com

デカルト積を行うための良いLINQ方法はありますか?

私はそのようなクラス構造を持っています:

Person
Dogs (dog 1, dog 2, etc)
Puppies (puppy A, puppy B, etc)

一人です。彼は1..n匹の犬を飼っています。各犬には1..nの子犬がいます。

各犬から1匹の子犬を取り、子犬の可能なすべての組み合わせのリストが必要です。例えば:

犬1子犬A、犬2子犬A犬1子犬A、犬2子犬B犬1子犬B、犬2子犬A犬1子犬B、犬2子犬B

それがsqlテーブルにあった場合、次のようにテーブルを「乗算」します。

select * from puppies a, puppies b where a.parent='dog1' and b.parent='dog2'

このちょっとしたことをするためにいくつかのlinq風の方法はありますか???

本当にありがとう

56
Chris

私が質問を理解していれば、n個の子犬のデカルト積が必要です。

コンパイル時にセットの数がわかっている場合は、デカルト積を簡単に取得できます。

from p1 in dog1.Puppies
from p2 in dog2.Puppies
from p3 in dog3.Puppies
select new {p1, p2, p3};

Dog1に子犬p11、p12、dog2に子犬p21、dog3に子犬p31、p32があるとします。これはあなたに与えます

{p11, p21, p31},
{p11, p21, p32},
{p12, p21, p31},
{p12, p21, p32}

各行は匿名型です。コンパイル時にセットがいくつあるかわからない場合は、少し作業を増やして行うことができます。主題に関する私の記事を参照してください:

http://ericlippert.com/2010/06/28/computing-a-cartesian-product-with-linq/

そしてこのStackOverflowの質問:

可能なすべての組み合わせの生成

メソッドを取得したらCartesianProduct<T>その後、次のように言うことができます

CartesianProduct(from dog in person.Dogs select dog.Puppies)

取得するため

{p11, p21, p31},
{p11, p21, p32},
{p12, p21, p31},
{p12, p21, p32}

ここで、各行は子犬のシーケンスです。

理にかなっていますか?

83
Eric Lippert

dogs.Join(puppies、()=> true、()=> true、(one、two)=> new Tuple(one、two));

通常の結合を実行できますが、すべての組み合わせを有効にしたいため、セレクターはどちらも同じ値を返します。組み合わせるときは、両方を1つのタプル(または選択した別のデータ構造)に入れます。

leftSide.SelectMany((l) => rightSide, (l, r) => new Tuple(l, r));

これはデカルト積を実行するはずです。

18
McKay

犬と子犬のすべての可能な組み合わせが必要な場合は、クロス結合を実行します。

from dog in Dogs
from puppy in Puppies
select new
{
    Dog = dog,
    Puppy = puppy
}
14