如何应用Seq map功能?

net*_*x01 3 f# seq

我最近一直在玩F#.我想知道而不是使用for循环来生成一个元素序列,它与列表中的每个其他元素相乘,我如何使用Seq map函数或类似的东西来生成类似下面的内容.

所以对于例如我有一个列表[1..10]我想应用一个产生类似结果的乐趣

[(1*1); (1*2);(1*3); (1*4); (1*5)......(2*1);(2*2);(2*3).....(3*1);(3*2)...]
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?

非常感谢你的帮助.

Mau*_*Mau 6

let list = [1..10]

list |> List.map (fun v1 -> List.map (fun v2 -> (v1*v2)) list) |> List.collect id
Run Code Online (Sandbox Code Playgroud)

最后的List.collect使列表列表变平.如果你想要一个懒惰的序列,它与Seq而不是List一样.

或者,使用collect作为主要的迭代器,如cfern建议和obsessivley消除匿名函数:

let flip f x y = f y x

let list = [1..10]

list |> List.collect ((*) >> ((flip List.map) list))
Run Code Online (Sandbox Code Playgroud)


cfe*_*ern 5

列表理解将是最简单的方法:

let allpairs L = 
    [for x in L do
        for y in L -> (x*y)]
Run Code Online (Sandbox Code Playgroud)

或者,不使用任何循环:

let pairs2 L = L |> List.collect (fun x -> L |> List.map (fun y -> (x*y)))
Run Code Online (Sandbox Code Playgroud)


编辑以回复评论: 您可以将自行交叉扩展方法添加到列表中,如下所示:

type Microsoft.FSharp.Collections.List<'a> with
    member L.cross f = 
        [for x in L do
            for y in L -> f x y]
Run Code Online (Sandbox Code Playgroud)

例:

> [1;2;3].cross (fun x y -> (x,y));;
val it : (int * int) list =
  [(1, 1); (1, 2); (1, 3); (2, 1); (2, 2); (2, 3); (3, 1); (3, 2); (3, 3)]
Run Code Online (Sandbox Code Playgroud)

我不会在F#中使用扩展方法,感觉有点C#'ish.但这主要是因为我觉得F#中不需要流畅的语法,因为我通常将我的函数与管道(|>)运算符链接在一起.

我的方法是使用交叉函数扩展List模块,而不是类型本身:

module List =
    let cross f L1 L2 = 
        [for x in L1 do
            for y in L2 -> f x y]
Run Code Online (Sandbox Code Playgroud)

如果这样做,您可以像使用List的任何其他方法一样使用cross方法:

> List.cross (fun x y -> (x,y)) [1;2;3] [1;2;3];;
val it : (int * int) list =
  [(1, 1); (1, 2); (1, 3); (2, 1); (2, 2); (2, 3); (3, 1); (3, 2); (3, 3)]
> List.cross (*) [1;2;3] [1;2;3];;
val it : int list = [1; 2; 3; 2; 4; 6; 3; 6; 9]
Run Code Online (Sandbox Code Playgroud)