Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# F列表SelectMany_F#_Linq - Fatal编程技术网

F# F列表SelectMany

F# F列表SelectMany,f#,linq,F#,Linq,这是一个非常简单的问题,但我没有找到答案: F中是否有任何Seq/List操作来匹配LINQ SelectMany 我知道我可以使用System.Linq in F,如果我 想。 我知道我可以做一个递归方法 并使用F计算表达式 制造更强大的东西。 但如果我试图证明F列表运算比LINQ更强大 .Where=List.filter .Select=List.map .Aggregate=List.fold ... 在C语言中,许多用法的语法非常简单: var flattenedList = from

这是一个非常简单的问题,但我没有找到答案:

F中是否有任何Seq/List操作来匹配LINQ SelectMany

我知道我可以使用System.Linq in F,如果我 想。 我知道我可以做一个递归方法 并使用F计算表达式 制造更强大的东西。 但如果我试图证明F列表运算比LINQ更强大

.Where=List.filter .Select=List.map .Aggregate=List.fold ... 在C语言中,许多用法的语法非常简单:

var flattenedList = from i in items1
                    from j in items2
                    select ...
有没有简单的直接匹配,List.flatte,List.bind之类的

SelectMany有几个签名,但最复杂的似乎是:

IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(
    this IEnumerable<TSource> source, 
    Func<TSource, IEnumerable<TCollection>> collectionSelector, 
    Func<TSource, TCollection, TResult> resultSelector
);
Seq.bind就是你想要的。SelectMany实际上只是一个一元绑定:

所以你会这样做:

seq { for i in items1 do
         for j in items2 do
            yield ....  };

您可以使用List.collect或Seq.collect:

let items1 = [1; 2; 3]
let items2 = [4; 5; 6]
let flat = items1 |> List.collect (fun i1 -> items2 |> List.map (fun i2 -> [i1, i2]))
这大致相当于以下C代码:

var flat = from i1 in items1
           from i2 in items2
           select new { i1, i2 };
collect相当于SelectMany,但它不提供所有重载。下面是如何制作您引用的一个

let selectMany (ab:'a -> 'b seq) (abc:'a -> 'b -> 'c) input =
    input |> Seq.collect (fun a -> ab a |> Seq.map (fun b -> abc a b))
// gives
// val selectMany : ('a -> seq<'b>) -> ('a -> 'b -> 'c) -> seq<'a> -> seq<'c>
F列表操作比LINQ更强大。。。虽然seq/list操作很棒,但一些真正的F能力来自和


其他帖子展示了如何将linq与

从这个linq开始:

var flattenedList = from i in items1
                    from j in items2
                    select ...
var flattenedList2 = items1.SelectMany(i => items2.Map(j => ...))
等效F为:

let flattenedList = seq {
    for a in items1 do
    for b in items2 do
        yield ... }
let flattenedList2 = items1 |> Seq.collect (fun i -> items2 |> Seq.map (fun j -> ...))
这两位代码在表达能力和复杂性上大致相当

话虽如此,让我们在您的帖子中发表一条具体评论:

但如果我试图证明F列表 行动比行动更强大 林克

Seq/List模块中的操作大致相当于可枚举/Linq扩展

然而,我要说的是,列表的杀手级功能是能够对它们进行模式匹配。下面是一个不容易转换为linq的愚蠢示例:

let rec funky = function
    | x::y::z::rest -> (z, y)::funky(z::x::rest)
    | [y;z]-> [(z, y)]
    | [z] -> [(z, z)]
    | [] -> []
// funky [1..6]
// = (int * int) list = [(3, 2); (4, 1); (5, 3); (6, 4)]

这在C中重新实现会有点尴尬,但是编写F非常简单。

有很多好的选项可以创建自己的SelectMany,但是直接使用SelectMany呢

let flatten (source : 'T seq seq) :'T seq =
    System.Linq.Enumerable.SelectMany(source, id)

这是对使用F的.net SelectMany的基本调用。

如何显示F列表比C列表更强大?如果这是一个问题,其中一个有更多的功能,这并不表明更强大,只是更臃肿。你是不是在试图用列表来证明你在F中可以做一些用C做不到的事情?我在F库或powerpack中都没有看到Seq.bind。你是说Seq.collect吗?你没有看到Seq.bind,因为它不是Seq模块中的函数;这是seq monoid下面的工作流生成器的一种方法。@pblasucci:原则上是的,但seq{..}不是真正的计算表达式。它是由编译器专门处理的,seq并不是一个真正的计算生成器,它只是一个函数seq。因此,Seq.collect是正确的答案,但它并没有真正用于序列表达式的编译形式SelectMany@Tomas:谢谢你的澄清。seq的特殊情况处理是因为它发生得如此频繁,因此需要特殊优化吗?
let flattenedList = seq {
    for a in items1 do
    for b in items2 do
        yield ... }
let flattenedList2 = items1 |> Seq.collect (fun i -> items2 |> Seq.map (fun j -> ...))
let rec funky = function
    | x::y::z::rest -> (z, y)::funky(z::x::rest)
    | [y;z]-> [(z, y)]
    | [z] -> [(z, z)]
    | [] -> []
// funky [1..6]
// = (int * int) list = [(3, 2); (4, 1); (5, 3); (6, 4)]
let flatten (source : 'T seq seq) :'T seq =
    System.Linq.Enumerable.SelectMany(source, id)