2017-01-22 55 views
2

我是Haskell中的新成員。我試圖用遞歸寫一個函數,給定兩個列表(它們需要是相同類型的),交織它們的元素(將元素在第一個和第二個列表之間交替)。當其中一個列表中沒有更多元素時,它會停止並且結果就是達到的列表。我輸出的如何從兩個列表中創建列表以及來自這些列表的元素

interChange :: [a] -> [b] ->[(a,b)] 
interChange _ [] = [] 
interChange [] _ = [] 
interChange (x:xs) (y:ys) = (x,y) : interChange xs ys 

例如:需要的輸出

interChange [1,2,3] [4,5,6] 
[(1,4),(2,5),(3,6)] 

例子是:

interChange [1,2,3] [4,5,6] 
[1,4,2,5,3,6] 

感謝您的幫助

回答

3

interChange是一樣的前奏的zip

ghci> zip [1,2,3] ["wibble", "wobble", "wubble"] 
[(1,"wibble"),(2,"wobble"),(3,"wubble")] 

要寫入指定的功能,你其實需要一雙列出了同類型的的。我們正在輸出一個特定類型的列表,所以進入該列表的所有元素也必須具有該類型。

interleave :: [a] -> [a] -> [a] 

你可以通過一個Bool圍繞表示這在遞歸的方式實現這個名單,你應該採取的下一個節點:

interleave = go True 
    where go _ [] ys = ys 
      go _ xs [] = xs 
      go True (x:xs) ys = x : go False xs ys 
      go False xs (y:ys) = y : go True xs ys 

評價go最後兩個分句,直到之間的平pongs任何一個輸入列表都是空的,因此我們只返回另一個列表的其餘部分。 (如果你想讓它更象zip你可以有它通過返回[]而不是xsys在這些情況下截斷輸出。)


但我始終建議避免遞歸在較高的水平,編程可能。我們可以將這個功能作爲管道:

  1. 配對使用zip
  2. 打開在結果列表中的每個元組爲兩個元素的列表輸入列表中的元素:map (\(x, y) -> [x, y])
  3. 拼合結果列表使用concat

-of-列表,使代碼看起來是這樣的:

interleave xs ys = concat $ map (\(x, y) -> [x, y]) $ zip xs ys 

我發現這個代碼比遞歸代碼更容易理解,它需要你推理控制流 - 它只是一系列高級指令。

順便說一句,你可以將它拖動到任意的concat的Elid中間mapzip

interleave xs ys = concatMap (\(x, y) -> [x, y]) $ zip xs ys 
interleave xs ys = concat $ zipWith (\(x, y) -> [x, y]) xs ys 
+0

非常感謝你的回放,你的代碼非常好。但是,它不能滿足最後的條件。當其中一個列表中沒有其他元素時,它停止。你的代碼給出如下輸出:[1,2,3,4] [6,7,8] = [1,6,2,7,3 ,8,4],但它應該是[1,6,2,7,3,8] –

+0

我相信你可以弄清楚如何修改代碼以適應練習。 –

2

interChange被稱爲有兩個非空列表(x:xs)(y:ys),輸出應該是一個列表開始x然後y然後更多的東西。所以你應該寫點類似於

interChange (x:xs) (y:ys) = x : y : ... 
相關問題