有没有一个很好的LINQ方式来做笛卡尔积?

时间:2010-11-01 22:43:15

标签: c# sql asp.net linq cartesian-product

我有类似的类结构:

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

有一个人。他有1只狗。每只狗都有1只小狗。

我想要列出所有可能的小狗组合,从每只狗中取出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-ish方式来做这件事???

非常感谢

3 个答案:

答案 0 :(得分:79)

如果我理解了这个问题,你需要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问题:

Generating all Possible Combinations

获得方法CartesianProduct<T>之后,您可以说

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

获取

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

每行都是一系列小狗。

有意义吗?

答案 1 :(得分:18)

<击>     dogs.Join(puppies,()=&gt; true,()=&gt; true,(one,two)=&gt; new Tuple(one,two));

您可以进行常规连接,但选择器都返回相同的值,因为我希望所有组合都有效。组合时,将两者放入一个元组(或您选择的不同数据结构)。

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

这应该是笛卡尔积。

答案 2 :(得分:13)

如果你想要狗和小狗的所有可能组合,你会做一个交叉连接:

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