交换榆树数组中的两个元素

Swap two elements in elm Array

我想做一个函数来交换数组中的两个元素。

显然,如果它被第一个元素触发 Up msg,则什么也不会发生。如果 Down 消息与最新元素相同。

我有以下代码:

module Main exposing (main)

import Browser
import Html exposing (Html, button, div, text)
import Html.Attributes exposing (class)
import Html.Events exposing (onClick)
import Array
import List exposing (map)

type alias Model = Array.Array Int


initialModel : Model
initialModel =
    Array.fromList [3, 1, 7, 2, 6, 4, 5]


type Msg
    = Up Int
    | Down Int


update : Msg -> Model -> Model
update msg model =
    case msg of
        Up n ->
           swap model n (n-1)
        Down n ->
           swap model n (n+1)

swap : Model -> Int -> Int -> Model
swap model src dest =
   model -- How do it?


view : Model -> Html Msg
view model =
    div [] (map elements (Array.toIndexedList model))

elements : (Int, Int) -> Html Msg
elements (position, number) =
  div [ class "block" ]
    [ button [ onClick (Up position) ] [ text "UP" ]
    , div [] [ text <| String.fromInt number ]
    , button [ onClick (Down position) ] [ text "DOWN" ]
    ]


main : Program () Model Msg
main =
    Browser.sandbox
        { init = initialModel
        , view = view
        , update = update
        }

而且我想知道使用 List 还是 Array 更好。

非常感谢

我通常更喜欢使用列表而不是数组,但如果您不打算向列表中添加新项目,数组可能更有意义。

Array 的优点是访问特定元素的速度更快,但如果您只有几个项目,您可能不必担心性能问题。同样,从 Array 转换为 List 也并非没有性能成本。

选项 1:如果您继续使用数组,您可以解决它,例如像这样:

  1. Get the valuessrcdest 中,如果其中之一 returns Nothing 提前退出(这将涵盖索引失效的情况范围)
  2. Set the value of src to dest 反之
  3. Return新数组

选项 2:如果您改用列表,您可以使用 elm-community/list-extra 包。
它有一个 swapAt 功能可以满足您的需要。

选项 3:可以为 List 或 Array 实现,但您需要实现一个自定义行为,遍历所有元素并构建一个新的 Array/List ,我认为现在超出了范围。

此致, 马克