#f#
#f#
Вопрос:
если у меня есть array A
, и у меня есть другой массив bool isChosen
с такой же длиной A
, A
как я могу создать новый массив из isChosen
того true
места, где он находится,,? что-то вроде A.[isChosen]
? Я не могу использовать Array.filter
напрямую, поскольку isChosen
это не функция A
элементов и не существует Array.filteri
подобного Array.mapi
.
Комментарии:
1. Похоже,
zip
это может быть удобно.
Ответ №1:
zip должен помочь:
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
Ответ №2:
Попробуйте использовать zip-оператор
seq.zip A isChosen
|> Seq.filter snd
|> Seq.map fst
|> Array.ofSeq
Это создаст последовательность кортежей, в которых одно значение берется из A
, а другое — из isChosen
. Это позволит связать значения вместе и очень легко отфильтровать их в Seq.filter
выражении
Комментарии:
1. 1, но обратите внимание, что
Seq.filter (fun (_, right) -> right)
это можно было бы упростить доSeq.filter snd
, а аналогично дляSeq.map (fun (left, _) -> left)
доSeq.map fst
.2. @ildjam спасибо за рекомендацию. Я часто забываю о помощниках по кортежам
Ответ №3:
Это не так элегантно или «функционально», как другие ответы, но время от времени мне нравится ненавязчивое напоминание о том, что вы можете использовать циклы и индексы массива в 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. моя первая попытка заключалась в использовании
->
вместоdo.. yield
. почему->
не работает? Спасибо2. Вы можете заменить
do yield
на->
синтаксис ‘short form’, если вы выполняете простое однострочное сопоставление, но если у вас есть какая-либо логика (например,if
), тогда ‘short form’ не существует. (Мне не нравится синтаксис ‘short form’, он добавляет мало значения и создает путаницу.)
Ответ №4:
И вот еще два способа, просто для демонстрации (даже) большего количества функций библиотеки 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
Мой личный фаворит для понятности (и, следовательно, удобства сопровождения): ответ деско
let r = [| for (v, f) in Seq.zip l f do if f then yield v|]