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 
+1

这工作完美。谢谢 – jynx678

古斯塔沃的回答应该解决您的递归,但目前还不清楚,如果你想练递归,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来显示结果。图书馆也有排列和变化,以及一个选项来产生重复或不(似乎这是默认)。