2015-12-29 80 views
3

更新元素我剛剛在榆樹開始編程和我堅持的東西:榆樹 - 在列表

我想有一個可以在一定的索引更新列表中元素的字段的方法。

簽名應該是這樣的:

updateElement : List (ID, Task) -> Int -> List (ID, Task) 

有:

type alias Task = 
    { description : String, focus : Bool} 

在這種情況下,我想設置任務的布爾(焦點)給予指數true和列表中的所有其他任務都爲false。

我已經嘗試過在Elm中的數組,但後來我必須與Maybe一起工作,並不認爲這是一個好的解決方案。

我想我將不得不使用'map'來更改列表中的元素,但我沒有任何線索可以在特定索引處更改它。

謝謝!

+0

你是不是指'List(Int,Task) - > Int - > List(Int,Task)'?或'列表(ID,任務) - > ID - >列表(ID,任務)'哪裏'類型別名ID = Int'? – robertjlooby

+0

另外'任務'可能是一個不錯的選擇,因爲已經有一個[任務](http://package.elm-lang.org/packages/elm-lang/core/3.0.0/Task)核心包 – robertjlooby

+0

確實是我的錯..簽名應該是 updateElement:列表(ID,任務) - >內部 - >表(ID,任務) ,我想更改列表的第n個元素 – Thibault

回答

4

現在你已經澄清你的問題,真正的答案是兩次更新的組合乍得發佈

updateElement : List (ID, Task) -> Int -> List (ID, Task) 
updateElement list indexToFocusOn = 
    let 
    toggle index (id, task) = 
     if index == indexToFocusOn then 
     (id, { task | focus = true }) 
     else 
     (id, { task | focus = false }) 
    in 
    List.indexedMap toggle list 
+0

感謝這工作! – Thibault

3

既然要更新列表中的所有元素(以確保所有元素是假,而那些匹配ID爲True),您可以執行List.map在列表中,同時提供他們的工作是檢查功能該索引並在元素上執行更新。

這裏有一些小的改動你的示例代碼示例:

type alias MyTask = 
    { description : String 
    , focus : Bool 
    } 

updateElement : List (a, MyTask) -> a -> List (a, MyTask) 
updateElement list id = 
    let 
    toggle (idx, task) = 
     if id == idx then 
     (idx, { task | focus = True }) 
     else 
     (idx, { task | focus = False }) 
    in 
    List.map toggle list 

我改變了你的簽名,以便更爲通用。既然你沒有提供什麼ID,我認爲元組中的第一個元素必須與第二個函數參數的類型相匹配。我還將Task替換爲MyTask,因爲已經有一個名爲Task的elm中的常見類型。

我還會提到有一個List.indexedMap函數可以讓你簡化你的函數聲明。如果你在上面的例子中有一個元組輸入輸出的唯一原因是因爲你需要通過它的索引來定位一個元素,那麼使用List.indexedMap可能更容易。這裏有一個例子:

updateElement2 : List MyTask -> Int -> List MyTask 
updateElement2 list id = 
    let 
    toggle idx task = 
     if id == idx then 
     { task | focus = True } 
     else 
     { task | focus = False } 
    in 
    List.indexedMap toggle list 

正如你所看到的,它減少了一些元組樣板出來的功能,使得它有點清潔。

+0

非常感謝對於你的答案,我可以在其他地方使用這個解決方案:-)但我爲我目前的問題misexpressed自己(對不起,我的第一篇文章..) 確實:類型別名ID = Int 但我想改變一個列表的第n個元素與n給定.. 所以簽名:updateElement :列表(ID,任務) - > Int - >列表(ID,任務) 我想這樣做,因爲我將排序列表,但焦點應該停留在列表中的相同位置。列表中的ID有其他功能 對不起,混淆,希望你仍然可以幫我.. – Thibault

2

如果你想經常更改只有列表的第n個元素,List會錯誤的數據結構。在elm中的List被實現爲鏈接列表,在隨機訪問的性能方面不會很好。

對於這類工作,您可能應該使用elm Array,而且Array確實有一個簡單的函數來設置第n個元素,其餘所有其他元素不變:Array.set :: Int -> a -> Array a -> Array a

關於該主題,this discussion on the elm bug tracker可能是有趣的。