Search code examples
listelm

More efficient way to update an element in a list in Elm?


Is there a more efficient way to update an element in a list in Elm than maping over each element?

{ model | items = List.indexedMap (\i x -> if i == 2 then "z" else x) model.items }

Maybe Elm's compiler is sophisticated enough to optimize this so that map or indexedMap isn't unnecessarily copying over every element except 1. What about nested lists?

Clojure has assoc-in to update an element inside a nested list or record (can be combined too). Does Elm have an equivalent?


Solution

  • More efficient in terms of amount of code would be (this is similar to @MichaelKohl's answer):

    List.take n list ++ newN :: List.drop (n+1) list
    

    PS: if n is < 0 or n > (length of list - 1) then the new item will be added before or at the end of the list.

    PPS: I seem to recall that a :: alist is slightly better performing than [a] ++ alist.

    If you mean efficient in terms of performance/ number of operations:

    As soon as your lists get large, it is more efficient to use an Array (or a Dict) instead of a List as your type.

    But there is a trade-off:

    • Array and Dict are very efficient/ performant when you frequently retrieve/ update/ add items.
    • List is very performant when you do frequent sorting and filtering and other operations where you actually need to map over the entire set.

    That is why in my code, List is what I use a lot in view code. On the data side (in my update functions) I use Dict and Array more.