2016-02-23 54 views
5

我有一個列表,並希望單獨返回每個元素。基本上就像從一個堆棧彈出。例如:將列表遞歸解壓縮到元素中

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))))) 

不幸的是我嘗試在遞歸解決方案,甚至更好的使用倍或掃描什麼是不成功的。例如,這只是返回列表(與地圖相同)。

let pop3 (rnds:int list) = 
    let rec pop3' rnds acc = 
     match rnds with 
     | head :: tail -> List.tail(tail) 
     | [] -> acc 
    pop3' [] rnds 

回答

2

這似乎是一個好奧珀蒂尼蒂一類

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

所以我會用它想:'讓XX = unpacker(rnds)''xx.get()'或'[for i in 1..5 - > xx.get()]'我添加了'覆蓋this.ToString()= sprintf「%A」l'它更友好一些。 – s952163

5

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]) 
+0

是的,的確是一個非常有趣的解決方案。非常感謝。 – s952163