![](/img/trans.png)
[英]Getting even and odd position of elements in list - Haskell Mutual Recursion
[英]separate even and odd elements of list haskell
我正在嘗試將列表的元素分成更多列表,一個用於奇數,一個用於偶數。
例如,
input: [1,2,3,4,10]
output: ([2,4,10],[1,3])
sepList :: [Int]->([Int],[Int])
sepList [] = ([],[])
sepList (x:xs) | (x mod 2) ==0 = (([x],[]) ++ sepList xs)
| (x mod 2) /=0 = (([],[x]) ++ sepList xs)
| otherwise = ([],[])
它在...++ sepList xs
上給出錯誤,有人可以在這里指導我嗎?
運算符++
用於連接2個列表,而++
的參數都不是列表,
([x],[]) ++ sepList xs
([x],[])
和sepList xs
都是列表對。 因此,您想要在sepList xs
上進行模式匹配,例如使用let
綁定,
let (ys,zs) = sepList xs in
然后返回
(x:ys,zs)
您沒有串聯兩個列表; 您想要將一個元素添加到列表中,該列表是從遞歸調用的元組輸出中選擇的。 不要使用(++)
; 使用(:)
。
sepList (x:xs) = let (evens, odds) = sepList xs
in if even x
then (x:evens, odds)
else (evens, x:odds)
不過,更簡單地說, sepList = partition even
。 (可以在Data.List
找到partition
。)
到目前為止,有兩個答案建議基本上是手動執行此操作(通過對遞歸調用的結果進行模式匹配),但是實際上已經為您使用的類型定義了一個運算符,它可以完全滿足您的要求! 列表以(<>) = (++)
構成一個monoid,但是您沒有兩個列表:您有兩對列表。 幸運的是,如果對中的每個元素都是一個對映體,則對的類型也是一個對映體: (a,b) <> (c,d) = (a <> c, b <> d)
。 因此,您可以簡單地用<>
替換++
調用,這將導致連接成對的相應列表。
對於發燒友來說,遵循一行也可以將偶數和奇數分開。
sepList xs = (filter even xs , filter odd xs)
import Data.List
sepList :: [Int]->([Int],[Int])
sepList = partition even
sepList [1,2,3,4,10]
在這種情況下,我將使用一個accumulator
來創建包含兩個列表的元組。在我們的示例中, accumulator
是([],[])
。
split::[Int]->([Int],[Int])
split ls= go ([],[]) ls where
go accu [] = accu
go (odd,even) (x:xs) | x `mod` 2==0 = go (x:odd,even) xs
| otherwise = go (odd, x:even) xs
如您所見,由於我們使用:
運算符將元素推到列表的頂部,因此需要反轉元素。
我不知道這是否是最佳的,但我會用它寫這樣的reverse
:
module Split where
split::[Int]->([Int],[Int])
split ls=let rev tupl=(reverse . fst $ tupl ,reverse .snd $ tupl) in
rev $ go ([],[]) ls where
go accu [] = accu
go (odd,even) (x:xs) | x `mod` 2==0 = go (x:odd,even) xs
| otherwise = go (odd, x:even) xs
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.