Как отфильтровать значения Nothing из массива Elm?

Я хотел бы определить следующую функцию:

compactAndConvertToList : Array (Maybe String) -> List String

Эта функция должна удалить все появления Nothing в данном массиве и преобразовать его в List.

Я придумал решение ниже, но оно кажется немного грязным.

Есть ли лучший способ добиться этого?

import Graphics.Element exposing (..)
import Array

model : Array.Array (Maybe String)
model = Array.fromList [ Just "Hello", Just "Stack", Nothing, Just "Overflow" ]


compactAndConvertToList : Array.Array (Maybe String) -> List String
compactAndConvertToList maybeStrings =
  maybeStrings
    |> Array.filter (\x -> x /= Nothing)
    |> Array.map (Maybe.withDefault "")
    |> Array.toList


main = 
  model
    |> compactAndConvertToList
    |> show

person Misha Moroshko    schedule 13.10.2015    source источник
comment
почему там () вокруг может быть строка? Я новичок в вязе. Почему (может быть, String) и что это делает с Array.Array?   -  person PositiveGuy    schedule 28.07.2018
comment
@PositiveGuy Без скобок вокруг Maybe String это будет интерпретироваться как два отдельных аргумента для Array.   -  person Dull Bananas    schedule 04.08.2020


Ответы (2)


Если вашим конечным результатом является список, вам, вероятно, лучше просто преобразовать массив в список, а затем работать с ним.

import Array 

compactAndConvertToList : Array.Array (Maybe String) -> List String
compactAndConvertToList = Array.toList >> List.filterMap identity

Если вас не устраивают функции высшего порядка, вы можете написать это так:

compactAndConvertToList arr = List.filterMap identity (Array.toList arr)

Мы берем наш массив, применяем к нему toList, затем применяем к нему filterMap. Карта фильтров берет функцию, которая выдает «может быть», и применяет ее к каждому элементу в списке, отбрасывая Nothing случаев. Мы просто применяем функции идентификации, которые отбрасывают уже имеющиеся Nothing значения.

В общем, массивы хороши для быстрого произвольного доступа, но если вы просматриваете всю коллекцию несколько раз, списки будут работать быстрее. Но всегда начинайте с простого, а затем оптимизируйте, если нужно.

person jmite    schedule 13.10.2015
comment
Большое спасибо! Мне нравится первая версия с >>. Несколько несвязанные вопросы относительно Array против List: построить модель, представляющую двумерный массив (для этой игры, например), лучше использовать Array из Arrays? Я не мог найти, как получить элемент по определенному индексу в List. - person Misha Moroshko; 13.10.2015
comment
Да, вам определенно не нужны списки для этого, поиск определенного элемента очень медленный. Array of Arrays - ваш лучший выбор. - person jmite; 13.10.2015

Возможно, это лучший ответ, как в 2018 году. Используйте elm-community /maybe-extra пакет.

Пример:

Maybe.Extra.values [Just 1, Nothing, Just 3]

Возвращает:

[1,3]
person Jakub Zawiślak    schedule 25.02.2018