代码之家  ›  专栏  ›  技术社区  ›  s952163

递归地将列表解压缩为元素

  •  4
  • s952163  · 技术社区  · 8 年前

    我有一个列表,希望逐个返回其中的每个元素。基本上就像从堆栈中弹出一样。例如:

    let rnd = new System.Random()
    let rnds = List.init 10 (fun _ -> rnd.Next(100))
    List.iter (fun x -> printfn "%A"x ) rnds
    

    然而,我不想迭代,而是希望一个接一个地返回每个整数,直到列表为空。所以基本上是这样的:

    List.head(rnds)
    List.head(List.tail(rnds))
    List.head(List.tail(List.tail(rnds)))
    List.head(List.tail(List.tail(List.tail(List.tail(rnds)))))
    

    不幸的是,我尝试使用折叠或扫描的递归解决方案甚至更好的解决方案都没有成功。例如,这只是返回列表(与map相同)。

    let pop3 (rnds:int list) =
        let rec pop3' rnds acc =
            match rnds with
            | head :: tail -> List.tail(tail)
            | [] -> acc
        pop3' [] rnds
    
    2 回复  |  直到 8 年前
        1
  •  5
  •   Mark Seemann    8 年前

    uncons 做你需要的吗?

    let uncons = function h::t -> Some (h, t) | [] -> None
    

    您可以使用它“弹出”列表的标题:

    > rnds |> uncons;;
    val it : (int * int list) option =
      Some (66, [17; 93; 33; 17; 21; 1; 49; 5; 96])
    

    您可以重复以下操作:

    > rnds |> uncons |> Option.bind (snd >> uncons);;
    val it : (int * int list) option = Some (17, [93; 33; 17; 21; 1; 49; 5; 96])
    > rnds |> uncons |> Option.bind (snd >> uncons) |> Option.bind (snd >> uncons);;
    val it : (int * int list) option = Some (93, [33; 17; 21; 1; 49; 5; 96])
    
        2
  •  2
  •   John Palmer    8 年前

    这似乎是一个很好的机会

    type unpacker(l) = 
        let mutable li = l
        member x.get() = 
            match li with
            |h::t -> li<-t;h
            |_ -> failwith "nothing left to return"