Far*_*ori 5 c# linq generics cartesian-product
我需要创建一系列列表的笛卡尔积.例如,我有:
{{4,3,7},{1,2,9},{5,8}}
我需要:{4,1,5},{4,1,8},{3,1,5},{3,1,8},......,{7,9,8}
到目前为止,我已经了解到你可以使用这样的东西:
var lists = new List<List<int>>
{
new List<int> { 4, 3, 7},
new List<int> { 1, 2, 9},
new List<int> { 5, 8},
};
IEnumerable<IEnumerable<int>> empty = new[] { Enumerable.Empty<int>() };
var agg = lists.Aggregate(
empty,
(acc, next)
=>
(from ac in acc
from n in next
select ac.Concat(new[] {n})));
Run Code Online (Sandbox Code Playgroud)
但是,最初当我实现这个时,我实现它是这样的:
var lists = new List<List<int>>
{
new List<int> { 4, 3, 7},
new List<int> { 1, 2, 9},
new List<int> { 5, 8},
};
var agg = lists.Aggregate(
new List<List<int>>() {new List<int> {}},
(acc, next)
=>
(from ac in acc
from n in next
select ac.Add(n)).ToList());
Run Code Online (Sandbox Code Playgroud)
此特定实现无法使用此错误进行编译:
在源类型为"System.Collections.Generic.List>"的查询表达式中,后续from子句中不允许使用类型为"System.Collections.Generic.List"的表达式.调用"SelectMany"时类型推断失败.
我对此错误消息感到有点困惑.我不明白为什么List不允许在那个位置?
错误消息的第一部分有点误导.以下将编译并正常工作:
var agg = lists.Aggregate(
new List<List<int>>(),
(acc, next)
=>
(from ac in acc
from n in next
// select ac.Add(n)).ToList());
select ac.Concat(new[] {n}).ToList()).ToList());
Run Code Online (Sandbox Code Playgroud)
真正的问题在于select ac.Add(n).select子句必须返回一个值(在本例中为a List<int>),但是您的调用将List<T>.Add修改原始列表并返回void.
在引擎盖下,LINQ尝试将此LINQ表达式转换为(除其他外)调用Enumerable.SelectMany.编译器传递的参数之一是生成的lambda表达式返回ac.Add(n)(即void).编译器尝试根据可用的重载来推断生成的lambda的类型SelectMany,但是没有兼容的重载,因此无法确定lambda的类型.因此错误消息"调用'SelectMany'时类型推断失败.".
同样Add,大多数List<T>方法通常不适合使用LINQ进行函数式编程,这就是为什么首选解决方案仅依赖于IEnumerable<T>与LINQ相关的扩展方法.
| 归档时间: |
|
| 查看次数: |
1283 次 |
| 最近记录: |