开发者

f# array.filter based on a bool array

if I have array A, and I have another bool array isChosen with the same length of A how can I build开发者_如何学JAVA a new array from A where isChosen is true? something like A.[isChosen]? I cannot use Array.filter directly since isChosen is not a function of A elements and there is no Array.filteri like Array.mapi.


zip should help:

let l = [|1;2;3|]
let f = [|true; false; true|]

let r = [| for (v, f) in Seq.zip l f do if f then yield v|]
// or
let r = (l, f) ||> Seq.zip |> Seq.filter snd |> Seq.map fst |> Seq.toArray 


Try the zip operator

seq.zip A isChosen 
|> Seq.filter snd
|> Seq.map fst
|> Array.ofSeq

This will create a sequence of tuples where one value is from A and the other is from isChosen. This will pair the values together and make it very easy to filter them out in a Seq.filter expression


It's not as elegant or 'functional' as the other answers, but every once in a while I like a gentle reminder that you can use loops and array indices in F#:

let A = [|1;2;3|]
let isChosen = [|true; false; true|]
let r = [| for i in 0..A.Length-1 do 
                if isChosen.[i] then 
                    yield A.[i] |]
printfn "%A" r

:)


And here are two more ways, just to demonstrate (even) more F# library functions:

let A = [|1;2;3|]
let isChosen = [|true;false;true|]

let B = Seq.map2 (fun x b -> if b then Some x else None) A isChosen
        |> Seq.choose id
        |> Seq.toArray

let C = Array.foldBack2 (fun x b acc -> if b then x::acc else acc) A isChosen []
        |> List.toArray

My personal favorite for understandability (and therefore maintainability): desco's answer

let r = [| for (v, f) in Seq.zip l f do if f then yield v|]
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜