Сортировка списка поплавков, входов или строк

Я пытаюсь сделать сортируемую таблицу, которая принимает различные виды данных. Перед отображением в виде сетки я преобразую все данные в строки (для представления). Тем не менее, elm не может правильно отсортировать список поплавков или входов, преобразованных в строки (вы заканчиваете чем-то вроде 1, 1001, 10.03, 21, 3.4, …).
У меня была идея создать тип объединения,

type ColType
    = StrCol String
    | IntCol String
    | FloatCol String
    | BoolCol String

Однако в какой-то момент мне нужно преобразовать обратно в String, если это StrCol, или Int, если IntCol и т. д., а затем сортировать; но я не уверен, как это сделать.

Спасибо за помощь.

Метки

2 ответа

  1. Можно просто создать функцию, которая преобразует содержимое каждого тега в строки:

    colTypeToString : ColType -> String
    colTypeToString colType =
        case colType of
            StrCol x -> toString x
            IntCol x -> toString x
            FloatCol x -> toString x
            BoolCol x -> toString x
    
  2. Вот пример, который вы можете попробовать.

    Я использовал Dictдля представления записи данных, где
    Valueможет быть либо FloatилиString, вместо
    определения ColType(ваше предложение).
    (Легко расширить для того чтобы поддержать другие comparableтипы.)

    -- MODEL
    type alias Model =
      { rows : List Row
      , cols : List String
      , sortkey : Maybe String
      }
    
    type alias Row = Dict.Dict String Value
    createRow : String -> Float -> Row
    createRow name val = Dict.fromList
      [ ("name", StrValue name)
      , ("value", FloatValue val)
      ]
    
    type Value
      = StrValue String
      | FloatValue Float
    
    init : (Model, Cmd Msg)
    init =
      let
        rows =
          [ createRow "A" 1.5
          , createRow "B" 0.5
          ]
        cols = ["name", "value"]
        sortkey = Nothing
      in (Model rows cols sortkey, Cmd.none)
    
    -- VIEW
    view : Model -> Html Msg
    view model =
      let
        renderRow cols row = tr [] <| List.map (renderValue row) cols
        renderValue row key = case (Dict.get key row) of
          Just (StrValue str) -> td [] [text str]
          Just (FloatValue num) -> td [] [text <| toString num]
          _ -> td [] [text "-"]
        renderHeaders cols = tr []
          <| List.map renderHeaderName model.cols
        renderHeaderName colname =
          th [ onClick (Sort colname) ]
            <| if Just colname == model.sortkey
               then [ text <| colname ++ "*" ]
               else [ text colname ]
      in
        table []
          <| [ renderHeaders model.cols ]
          ++ List.map (renderRow model.cols) model.rows
    
    -- UPDATE
    type Msg
      = Sort String
    
    update : Msg -> Model -> (Model, Cmd Msg)
    update msg model =
      case msg of
        Sort name ->
          let
            sortedRows = List.sortWith compareVal model.rows
            compareVal a b = case (Dict.get name a, Dict.get name b) of
              (Just (StrValue sa), Just (StrValue sb)) -> compare sa sb
              (Just (FloatValue na), Just (FloatValue nb)) -> compare na nb
              _ -> EQ
          in ({ model | rows = sortedRows, sortkey = Just name }, Cmd.none)