Получить значение индекса для определенных позиций в логическом массиве в F#

#f#

#f#

Вопрос:

У меня есть массив, который содержит только 0 и 1 . Давайте вызовем этот массив numbers . numbers Выглядит примерно так:

 val it : int [] =
  [|1; 1; 1; 1; 0; 1; 0; 1; 0; 0; 0; 1; 0; 1; 0; 0; 0; 1; 0; 1; 0; 0; 0; 1; 0;
   0; 0; 0; 0; 1; 0; 1; 0; 0; 0; 0; 0; 1; 0; 0; 0; 1; 0; 1; 0; 0; 0; 1; 0; 0;
   0; 0; 0; 1; 0; 0; 0; 0; 0; 1; 0; 1; 0; 0; 0; 0; 0; 1; 0; 0; 0; 1; 0; 1; 0;
   0; 0; 0; 0; 1; 0; 0; 0; 1; 0; 0; 0; 0; 0; 1; 0; 0; 0; 0; 0; 0; 0; 1; 0; 0;
   ...|]
 

Я хочу получить значение индексов, где 1 происходит. Например, в приведенном выше массиве индексы 0 , 1 , 2 , 3 , 5 и так далее имеют 1 . Мне нужен массив, который будет выглядеть следующим образом: [| 0; 1; 2; 3; 5; ... |] . Как я могу это сделать?

Ответ №1:

 [| 1; 0; 1; 1; 0 |]
|> Array.indexed
|> Array.choose (function (i, n) when n = 1 -> Some i | _ -> None)
// 0; 2; 3
 

Ответ №2:

Это работает, хотя я все еще новичок в F #, и мне интересно, есть ли более элегантное решение

 [| 1; 1; 0; 1; 0; 1 |]
|> Array.indexed
|> Array.filter (fun tuple -> snd tuple = 1)
|> Array.map fst
|> printf "%A"  

(* prints: [|0; 1; 3; 5|] *)
 

Пояснения:

  • Разверните элементы массива, чтобы получить массив кортежей (index, value)
  • отфильтруйте элементы, которые не соответствуют условию для значения,
  • Затем возьмите только первую часть каждого кортежа (индекс)

Вы также можете превратить это в более общую вспомогательную функцию, которую можно использовать с любым условием («предикатом»):

 let findAllIndices predicate =
    Array.indexed
    >> Array.filter (snd >> predicate)
    >> Array.map fst

[| 1; 1; 0; 1; 0; 1 |]
|> findAllIndices (fun x -> x = 1)
|> printf "%A"
 

Комментарии:

1. Используйте Array.indexed вместо Array.mapi

2. @BentTranberg действительно, я пропустил это, спасибо!

Ответ №3:

Система.Версия Linq

 open System.Linq

[<EntryPoint>]
let main argv =
    let it : int [] = [|1; 1; 1; 1; 0; 1;|]

    let values = it.Select(fun n i -> if n = 1 then i else -1).Where(fun i -> i >= 0).ToList();
    
    for v in values do
        printf "%A " v

    0