2016-02-23 13 views
5

Ich habe eine Liste und möchte jedes Element einzeln davon zurückgeben. Im Grunde wie von einem Stapel knallen. Zum Beispiel:Liste in Elemente rekursiv entpacken

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

jedoch statt Iterieren, würde Ich mag eigentlich jede ganze Zahl nacheinander zurückzukehren, bis die Liste leer ist. Also im Grunde etwas entlang der Linien von:

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

Leider meinen Versuchen einer rekursiven Lösung oder besser noch etwas mit Falt- oder Scan waren erfolglos. Zum Beispiel gibt dies nur die Liste (wie Karte) zurück.

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

Antwort

2

Dies scheint ein guter oppurtunity für eine Klasse

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

So würde ich es mag: 'lassen xx = Entpacker (rnds) '' xx.get() 'oder' [für i in 1..5 -> xx.get()] 'Ich habe' override this.ToString() = sprintf "% A" l' hinzugefügt es ist ein bisschen benutzerfreundlicher. – s952163

5

Would uncons tun, was Sie brauchen?

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

Sie können es verwenden, um 'Pop' den Kopf einer Liste:

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

du wiederholen:

> 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

Ja, tatsächlich eine sehr interessante Lösung. Vielen Dank. – s952163

Verwandte Themen