Linq to foreach没有中间选择(笛卡尔积)

时间:2017-11-10 01:16:53

标签: c# linq

给出

var query = 
  from dog in Dogs
  from puppy in Puppies
  select new
  {
    Dog = dog,
    Puppy = puppy
  };
  foreach (var pair in q)
  {
    adopt(pair.Dog, pair.Puppy);
  }

有没有办法切出中间选择,并立即调用动作采用?

编辑:我正在寻找的结果肯定是笛卡尔产品,只是名字可能略有偏差,因为我无法想到一个好的命名方案。

Dogs = [1,2,3], Puppies = [a,b,c]
call adopt 9 times, in any order, for all combinations
e.g. 1,a 1,b 1,c 2,a 2,b 2,c 3,a 3,b 3,c

EDIT2

我错误地声称在没有库的评论中可能是Java,这是我能得到的最接近的。

    IntStream dogs = IntStream.range(1, 4);
    IntStream puppies = IntStream.range(1, 4);
    dogs.forEach(
            d -> puppies.forEach(p ->
                adopt(d, p)
            )
    );
}

public static void adopt(int dog, int puppy){

}

2 个答案:

答案 0 :(得分:3)

您总是可以编写此扩展方法:

public static class ForEachEx
{
    public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
    {
        foreach (var item in source) action(item);
    }
}

然后您可以执行以下任一选项:

//option #1
Dogs
    .SelectMany(d => Puppies, (Dog, Puppy) => new { Dog, Puppy })
    .ForEach(pair => Adopt(pair.Dog, pair.Puppy));

//option #2
Dogs.ForEach(d => Puppies.ForEach(p => Adopt(d, p)));

答案 1 :(得分:1)

如果两个集合都是List<T>,则列表具有ForEach方法:

Dogs.ForEach(dog => 
    Puppies.ForEach(puppy => 
        adopt(dog, puppy)));

但它会比简单嵌套的foreach循环慢:

foreach (var dog in Dogs) 
    foreach (var puppy in Puppies) 
        adopt(dog, puppy);

如果adopt返回一个值,则:( .Count用于枚举SelectMany结果)

Dogs.SelectMany(dog => Puppies, adopt).Count();

如果adopt没有返回值,那么它会变得有点难看:

Dogs.SelectMany(dog => Puppies, (dog, puppy) => { adopt(dog, puppy); return 0; }).Count();