0

このコードは、リストを取得し、分割の瞬間にfalseを返す述語によって、リストを2つの部分に分割しています。

let split pred ys =
    let rec split' l r = 
        match r with
        | [] -> []
        | x::xs -> if pred (x::l) then x::(split' (x::l) xs) else []
    let res = split' [] ys
    let last = ys |> Seq.skip (Seq.length res) |> Seq.toList
    (res, last)

誰かがF#でそれを行うためのより最適で簡単な方法を知っていますか?

4

3 に答える 3

2

末尾再帰にすることはできますが、リストを逆にする必要があります。いつでも再帰ループから抜け出すことができるので、折りたたむ必要はありません。私は少しテストを行いましたが、リストを逆にすることは末尾再帰で補う以上のものです。

// val pred : ('a list -> bool)
let split pred xs =
    let rec split' l xs ys = 
        match xs with
        | [] -> [], ys
        | x::xs -> if pred (x::l) then (split' (x::l) xs (x::ys)) else x::xs, ys 
    let last, res = split' [] xs []
    (res |> List.rev, last)

ブライアンに似たバージョンで、末尾再帰であり、単一の値の述語を取ります。

// val pred : ('a -> bool)
let split pred xs =
    let rec split' xs ys =
        match xs with
        | [] -> [], ys
        | x::xs -> if pred x then (split' xs (x::ys)) else (x::xs), ys
    let last, res = split' xs []
    (res |> List.rev, last)

これは、述語がSeq.takeWhileのようなfalseを返すとすぐに要素の取得を停止するという点で、ライブラリ関数パーティションとは異なります。

// library function
let x, y = List.partition (fun x -> x < 5) li
printfn "%A" x  // [1; 3; 2; 4]
printfn "%A" y  // [5; 7; 6; 8]

let x, y = split (fun x -> x < 5) li
printfn "%A" x  // [1; 3]
printfn "%A" y  // [5; 7; 2; 4; 6; 8]
于 2009-11-10T23:57:48.530 に答える
0

末尾再帰ではありませんが、次のようになります。

let rec Break pred list =
    match list with
    | [] -> [],[]
    | x::xs when pred x -> 
        let a,b = Break pred xs
        x::a, b
    | x::xs -> [x], xs

let li = [1; 3; 5; 7; 2; 4; 6; 8]
let a, b = Break (fun x -> x < 5) li    
printfn "%A" a  // [1; 3; 5]
printfn "%A" b  // [7; 2; 4; 6; 8]

// Also note this library function
let x, y = List.partition (fun x -> x < 5) li
printfn "%A" x  // [1; 3; 2; 4]
printfn "%A" y  // [5; 7; 6; 8]
于 2009-11-11T01:15:34.827 に答える
0

ここにいくつかのフォルダの方法があります:

let split' pred xs = let f (ls,rs,cond) x = if cond (ls@[x]) then (ls@[x],rs,cond) else (ls,rs@[x],(fun _->false))
                     let ls,rs,_ = List.fold f ([],[],pred) xs
                     ls, rs
于 2009-11-13T12:34:15.380 に答える