2013-10-03 154 views
2

我想做一個程序insertAt其中z是列表中的位置,y是插入到列表xs中的數字。對於haskell來說,這是我迄今爲止所做的。在特定位置插入一個整數到列表中

insertAt :: Int-> Int-> [Int]-> [Int] 
insertAt z y xs 
    | z==1 = y:xs 

但我不知道該從哪裏去。

我有一個ElementAt的功能,其中

elementAt v xs 
    | v==1 = head xs 
    | otherwise = elementAt (v-1) (tail xs) 

,但我不知道我怎麼能適應它,或者如果我甚至需要。如果可能的話,我想避免追加。

回答

4

您可以在索引z處拆分列表,然後將列表的第一部分與元素(使用++ [y])連接起來,然後連接列表的第二部分。但是,這會創建一個新列表,因爲默認情況下數據是不可變的。列表中的第一個元素按照慣例具有索引0(因此如果您想要第一個元素的含義由1索引,則相應地調整z)。

insertAt :: Int -> Int-> [Int] -> [Int] 
insertAt z y xs = as ++ (y:bs) 
        where (as,bs) = splitAt z xs 
4

如果這不是功課:let (ys,zs) = splitAt n xs in ys ++ [new_element] ++ zs

對於此文章中,我將假設你正在做的這個問題,因爲功課或教自己如何做這種事情的其餘部分。

這種問題的關鍵是把它分解成它自然的情況。您正在處理兩條數據:您要插入的列表以及該列表中的位置。在這種情況下,每一條數據都有兩個自然情況:您處理的列表可以是空或不是,您正在處理的數字可以是零或不是。所以第一步是寫出來的所有四種情況:

insertAt 0 val []  = ... 
insertAt 0 val (x:xs) = ... 
insertAt n val []  = ... 
insertAt n val (x:xs) = ... 

現在,每一個的這四種情況下,你需要思考的答案應該給什麼,你在這種情況下是。

對於前兩種情況,答案很簡單:如果您想插入列表的前面,只需在開始處粘貼您感興趣的值,無論列表是否爲空。

第三種情況表明,問題實際上存在一個模棱兩可的問題:如果要求您插入空的列表的第三個位置,會發生什麼?聽起來對我來說是一個錯誤,但你必須爲自己回答你想要做的事情。

第四種情況非常有趣:假設您想要將值插入非空列表的非首位。在這種情況下,請記住,您可以使用遞歸來解決問題的較小實例。在這種情況下,您可以使用遞歸來解決,例如,insertAt (n-1) val xs - 也就是將相同的值插入到輸入列表的尾部n-1 th位置的結果。例如,如果您嘗試將5插入列表[100,200,300]的位置3(第四位置),則可以使用遞歸將5插入列表[200,300]的位置2(第三位置),這意味着遞歸調用將生成[200,300,5]

我們可以只是假設遞歸調用將工作;我們現在唯一的工作就是將答案轉化爲解決原來問題的答案。我們在這個示例中想要的答案是[100,200,300,5](將5插入列表[100,200,300]的位置4的結果,我們擁有的是列表[200,300,5]。那麼我們如何才能得到我們想要的結果?只需在第一個元素上加上! (想想爲什麼這是真的。)

在這種情況下,我們已經涵蓋了列表和位置組合更新的所有可能情況。由於我們的功能將正確地適用於所有可能性,並且我們的可能性涵蓋所有可能性可能的輸入,這意味着我們的功能將始終正常工作,所以我們完成了!所以我們完成了!

我會留給你來把這些想法翻譯成Haskell,因爲練習的目的是讓你學習它,但希望那可以讓你知道如何解決問題。

相關問題