我必须将列表分成两半,从而产生列表前半部分和列表(half1, half2)
的后半部分的元组。当此列表的长度为奇数时,我想让half1
包含的元素多于half2
。
halve :: [a] -> ([a],[a])
halve [] = ([],[])
halve xs =
if (((length(xs) `mod` 2)==1))
then(take (ceiling(toRational(length(xs) `div` 2))) xs, drop(ceiling(toRational(length(xs) `div` 2))) xs)
else ((take (floor(toRational(length(xs) `div` 2))) xs, drop (floor(toRational(length(xs) `div` 2))) xs))
main = do
putStrLn(show (halve [1,2,3])) gives me [1],[2,3] instead of [1,2],[3]
putStrLn(show (halve [])) gives me an error
这让我觉得在mod操作或限制操作中会发生一些截断。 我知道对于putStrLn(show(halve []))的错误,解释器不知道数组是由什么组成的,但我怎么能这样做以使类型无关紧要?我希望那条线能给我([],[])。
答案 0 :(得分:1)
您是否尝试过以下操作:
halve :: [a] -> ([a], [a])
halve xs = let n = div (length xs + 1) 2
in (take n xs, drop n xs)
-- or alternatively
halve :: [a] -> ([a], [a])
halve xs = splitAt (div (length xs + 1) 2) xs
div
函数向下舍入(下限)正商数并向上舍入(ceils)负商:
div 5 2 => 2
div -5 2 => -2
div 6 2 => 3
div -6 2 => -3
halve
函数的工作方式正如您所期望的那样:
halve [] => ([], [])
halve [1..5] => ([1,2,3], [4,5])
halve [1..6] => ([1,2,3], [4,5,6])
我不明白为什么你需要一个if then else
分支。你的功能不必要地复杂。