我是f#
的新手我试着计算一系列数字的笛卡尔积。我“借”了这个。
let xs = [1..99]
let ys = [1..99]
seq {for x in xs do for y in ys do yield x * y}
有更好或更优雅的方式吗?
加里
答案 0 :(得分:9)
基于List模块提供的功能解决问题的另一个可能性是:
let xs = [1..99]
let ys = [1..99]
let zs = xs |> List.collect (fun x -> ys |> List.map (fun y -> x*y))
避免了对.concat的额外调用,也应该完成这项工作。
但我坚持你的解决方案。它应该是最可读的,是真正的对手。 (只是试着大声读出这些代码。你的完全可以理解,Noldorins或我的不是。)
答案 1 :(得分:7)
免责声明:我没有安装当前F#的机器,所以我无法测试我的代码。但是,基本上,如果您从Haskell窃取sequence
,您可以将程序编写为
let cartesian = sequence >> List.map product
并将其作为
运行cartesian [[1..99]; [1..99]]
以下是编写sequence
的方法。它是您编写的序列表达式的通用版本。它只处理无限数量的列表:{ for x in xs do for y in ys do for z in zs ... yield [x;y;z;...] }
。
let rec sequence = function
| [] -> Seq.singleton []
| (l::ls) -> seq { for x in l do for xs in sequence ls do yield (x::xs) }
// also you'll need product to do the multiplication
let product = Seq.fold_left1 ( * )
然后你可以把你的程序写成
let cartesian xs ys = [xs; ys] |> sequence |> List.map product
// ... or one-argument, point-free style:
let cartesian' = sequence >> Seq.map product
您可能需要将某些Seq
更改为List
s。
但是,能够猜出非一般列表理解含义的人数可能比识别名称sequence
要多得多,所以你可能更适合使用列表理解。但是,只要你想运行整个计算表达式列表,sequence
就会派上用场。
答案 2 :(得分:2)
确实有一种稍微优雅的方式(至少在功能意义上)计算笛卡尔积,它使用List
类中存在的函数。 (这里不需要涉及序列或循环,至少不是直接涉及。)
试试这个:
let xs = [1..99]
let ys = [1..99]
xs |> List.map(fun x -> ys |> List.map(fun y -> x * y)) |> List.concat
虽然稍微长一点,虽然风格更加实用,但看起来还是如此。