F#9名称分解为2,3和4的不相关组合
问题描述:
我对F#很新,并且一直在寻找并运行我在网上找到的简单问题的示例。我偶然发现了一个似乎不起作用的工具,我希望有人能够解释这段代码中发生了什么,以及为什么。该函数应返回1260个不同的选项列表,而是它返回一个空列表[]F#9名称分解为2,3和4的不相关组合
let rec group ns xs =
let rec combination n xs =
match n, xs with
| 0, xs -> [([], xs)]
| _, [] -> []
| n, x::xs ->
let ts = [for ys, zs in combination(n-1) xs do yield (x::ys, zs)]
let ds = [for ys, zs in combination n xs do yield (ys, x::zs)]
ts @ ds
match ns, xs with
| [], _ -> ([])
| n::ns, xs ->
[for g, rs in combination n xs do
for gs in group ns xs do
yield g::gs]
[<EntryPoint>]
let main argv =
let list = ["One"; "Two"; "Three"; "Four"; "Five"; "Six"; "Seven"; "Eight"; "Nine"]
let groupSizes = [2;3;4]
printfn "%A" <| group groupSizes list
答
在第二for
看,似乎你正在使用在同一时间循环和递归。
如果你想使用递归那么你并不需要循环,递归循环会为你,尝试最后一行更改为此:
| n::ns, xs ->
[for g, rs in combination n xs do
yield g
yield! group ns xs]
这里yield!
相当于::
操作,我意味着你也可以写这样的:
[for g, rs in combination n xs do yield g] :: group ns xs
注意,即rs
没有使用,所以你可以写_
:
[for g, _ in combination n xs do yield g] :: group ns xs
最后请注意,你可以使用一个map
而是与功能fst
:
List.map fst (combination n xs do yield g) :: group ns xs
答
古斯塔沃的回答应该解决您的递归,但目前还不清楚,如果你想练递归,F#,或组合学。因此,如果你做了很多类似的问题,甚至要仔细检查输出,你可以在.NET中使用combinatorics library。例如:
#r @"..\packages\Combinatorics.1.0.3.2\lib\net40\Combinatorics.dll"
open Combinatorics.Collections
let list = ResizeArray["One"; "Two"; "Three"; "Four"; "Five"; "Six"; "Seven"; "Eight"; "Nine"]
let groupSizes = [2;3;4]
groupSizes
|> Seq.collect (fun x -> Combinations<string>(list,x))
|> Seq.toList
//|> Seq.length
我做只有一个变化,因为库的预期,泛型集合,我用ResizeArray
,这只是一般的C#列表。 Seq.collect
会将这三个集合合并为一个,最后使用Seq.toList来显示结果。图书馆也有排列和变化,以及一个选项来产生重复或不(似乎这是默认)。
这工作完美。谢谢 – jynx678