f # array.filter на основе массива bool - PullRequest
1 голос
/ 18 мая 2011

, если у меня есть массив A, и у меня есть другой массив bool isChosen с такой же длиной A, как я могу построить новый массив из A, где isChosen равно true?что-то вроде A.[isChosen]?Я не могу использовать Array.filter напрямую, поскольку isChosen не является функцией A элементов, и нет Array.filteri, как Array.mapi.

Ответы [ 4 ]

7 голосов
/ 18 мая 2011

Почтовый индекс должен помочь:

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 
3 голосов
/ 18 мая 2011

Попробуйте оператор zip

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

Это создаст последовательность кортежей, где одно значение от A, а другое от isChosen.Это объединит значения воедино и упростит их фильтрацию в выражении Seq.filter

2 голосов
/ 18 мая 2011

Это не так элегантно или «функционально», как другие ответы, но время от времени мне нравится мягкое напоминание, что вы можете использовать циклы и индексы массивов в 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

:)

1 голос
/ 18 мая 2011

И вот еще два способа, просто чтобы продемонстрировать (даже) больше функций библиотеки F #:

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

Мой личный фаворит за понятность (и, следовательно, удобство обслуживания): ответ Desco

let r = [| for (v, f) in Seq.zip l f do if f then yield v|]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...