我正在尝试将列表中的元素分成更多列表,一个用于奇数,另一个用于偶数。
例如,
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
上显示错误
有人可以在这里引导我吗?
答案 0 :(得分:4)
运算符++
用于连接2个列表,并且++
的自变量都不是列表,
([x],[]) ++ sepList xs
([x],[])
和sepList xs
都是列表对。因此,您要在sepList xs
上进行模式匹配,例如使用let
绑定
let (ys,zs) = sepList xs in
然后返回,
(x:ys,zs)
答案 1 :(得分:4)
您没有串联两个列表;您要向列表中添加单个元素 ,该列表是从递归调用的元组输出中选择的。不要使用(++)
;使用(:)
。
sepList (x:xs) = let (evens, odds) = sepList xs
in if even x
then (x:evens, odds)
else (evens, x:odds)
更简单地说,sepList = partition even
。 (partition
在Data.List
中。)
答案 2 :(得分:2)
到目前为止,有两个答案建议基本上是手动执行此操作(通过对递归调用的结果进行模式匹配),但是实际上已经为要使用的类型定义了一个运算符你想要什么!列表与(<>) = (++)
构成一个Monoid,但是您没有两个列表:您有两个对个列表。令人高兴的是,如果对中的每个元素都是一个对映体:(a,b) <> (c,d) = (a <> c, b <> d)
,则对的类型也是一个对映体。因此,您可以简单地将++
调用替换为<>
,这将导致连接成对的相应列表。
答案 3 :(得分:1)
对于发烧友来说,只需一行以下即可将列表分为偶数和奇数。
sepList xs = (filter even xs , filter odd xs)
答案 4 :(得分:1)
import Data.List
sepList :: [Int]->([Int],[Int])
sepList = partition even
sepList [1,2,3,4,10]
答案 5 :(得分:0)
在这种情况下,我将使用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