Scott Nimrod
Scott Nimrod

Reputation: 11595

How do I update an item within a list and maintain its index?

How do I update an item within a list?

I tried the following:

setFeaturedLink links link =
    let
        dictionary =
            Dict.fromList links

        result =
            Dict.filter (\k v -> v.title == link.title) dictionary |> Dict.toList |> List.head

        index =
            case result of
                Just kv ->
                    let
                        ( i, _ ) =
                            kv
                    in
                        i

                Nothing ->
                    -1
    in
        if not <| index == -1 then
            Dict.update index (Just { link | isFeatured = isFeatured }) dictionary |> Dict.values
        else
            []

The 2nd argument to function update is causing a mismatch.

59| Dict.update index (Just { link | isFeatured = isFeatured }) dictionary ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Function update is expecting the 2nd argument to be:

Maybe
    { contentType : ContentType
    , profile : Profile
    , title : Title
    , topics : List Topic
    , url : Url
    , isFeatured : Bool
    }
-> Maybe
       { contentType : ContentType
       , isFeatured : Bool
       , profile : Profile
       , title : Title
       , topics : List Topic
       , url : Url
       }

But it is:

Maybe
    { contentType : ContentType
    , isFeatured : Bool
    , profile : Profile
    , title : Title
    , topics : List Topic
    , url : Url
    }

Hint: It looks like a function needs 1 more argument.

Is there a simple example of how I can update an arbitrary item within a list?

Upvotes: 1

Views: 615

Answers (2)

pdoherty926
pdoherty926

Reputation: 10349

Is there a simple example of how I can update an arbitrary item within a list?

How about something like this, which is loosely based on the code you've provided:

import Html exposing (text)
import List

type alias Thing = { title: String, isFeatured: Bool }

bar = (Thing "Bar" False)

things = [(Thing "Foo" False), 
         bar]

featureThing things thing = 
  List.map (\x -> if x.title == thing.title 
                    then { x | isFeatured = True} 
                    else x) 
           things

updatedThings = featureThing things bar

main =
  text <| toString updatedThings
  -- [{ title = "Foo", isFeatured = False },
  --  { title = "Bar", isFeatured = True }]

I should also note that if ordering is important, a more robust approach would be to add an index field to your record and sort the list if/when necessary.

Upvotes: 1

Igor Drozdov
Igor Drozdov

Reputation: 15045

Yes, you can just map the links to links with updated value:

let
  updateLink l =
    if l.title == link.title then
      { l | isFeatured = True }
    else
      l
in
  List.map updateLink links

To be honest, I don't understand what isFeatured is in your code, but I assume you want to update it to True if link.title matches.

Upvotes: 3

Related Questions