65

我有一个像这样的类结构:

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-ish方式来做这种事情???

非常感谢

4

3 回答 3

96

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

每行是一系列小狗。

说得通?

于 2010-11-01T22:59:59.770 回答
24

dog.Join(puppies, () => true, () => true, (一, 二) => new Tuple(一, 二));

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

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

这应该做一个笛卡尔积。

于 2010-11-01T22:46:27.090 回答
15

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

from dog in Dogs
from puppy in Puppies
select new
{
    Dog = dog,
    Puppy = puppy
}
于 2010-11-01T22:51:36.677 回答