【问题标题】:Generate powerset lazily懒惰地生成powerset
【发布时间】:2011-12-31 03:37:44
【问题描述】:

我想计算一组的幂集。因为我一次不需要整个powerset,所以最好懒惰地生成它。

例如:

powerset (set ["a"; "b"; "c"]) =
seq {
  set [];
  set ["a"];
  set ["b"];
  set ["c"];
  set ["a"; "b"];
  set ["a"; "c"];
  set ["b"; "c"];
  set ["a";"b"; "c"];
}

由于结果是一个序列,我更喜欢上面的顺序。如何在 F# 中以惯用的方式做到这一点?

编辑:

这就是我要使用的(基于 BLUEPIXY 的回答):

let powerset s =
    let rec loop n l =
        seq {
              match n, l with
              | 0, _  -> yield []
              | _, [] -> ()
              | n, x::xs -> yield! Seq.map (fun l -> x::l) (loop (n-1) xs)
                            yield! loop n xs
        }   
    let xs = s |> Set.toList     
    seq {
        for i = 0 to List.length xs do
            for x in loop i xs -> set x
    }

感谢大家的出色意见。

【问题讨论】:

    标签: f# lazy-evaluation powerset


    【解决方案1】:
    let rec comb n l =
      match n, l with
      | 0, _  -> [[]]
      | _, [] -> []
      | n, x::xs -> List.map (fun l -> x ::l) (comb (n - 1) xs) @ (comb n xs)
    
    let powerset xs = seq {
        for i = 0 to List.length xs do
          for x in comb i xs -> set x
      }
    

    演示

    > powerset ["a";"b";"c"] |> Seq.iter (printfn "%A");;
    set []
    set ["a"]
    set ["b"]
    set ["c"]
    set ["a"; "b"]
    set ["a"; "c"]
    set ["b"; "c"]
    set ["a"; "b"; "c"]
    val it : unit = ()
    

    【讨论】:

    • 请注意,您也可以让 comb 返回一个序列,如果不枚举整个 powerset,则在某些情况下需要更少的计算。
    【解决方案2】:

    来自F# for Scientists,稍微修改为懒人

    let rec powerset s = 
      seq {
        match s with
        | [] -> yield []
        | h::t -> for x in powerset t do yield! [x; h::x]
      }
    

    【讨论】:

    • 这既美观又高效。唯一的问题是顺序不正确:)
    【解决方案3】:

    这是另一种方法,使用数学而不是递归:

    let powerset st =
        let lst = Set.toList st     
        seq [0..(lst.Length |> pown 2)-1] 
            |> Seq.map (fun i -> 
                set ([0..lst.Length-1] |> Seq.choose (fun x -> 
                    if i &&& (pown 2 x) = 0 then None else Some lst.[x])))
    

    【讨论】:

    • 参见“我更喜欢上面的顺序。”
    • 我明白了,但上面写着“我更喜欢”。然而,我的意图主要是展示一种不同的方法,使用数学但仍然很懒。
    猜你喜欢
    • 2010-09-26
    • 1970-01-01
    • 2019-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多