简单的haskell拆分列表

dbf7pr2w  于 2022-11-14  发布在  其他
关注(0)|答案(3)|浏览(197)

我有下面的函数,它接受一个列表,并返回在给定元素n处拆分的两个子列表。然而,我只需要将其拆分为两半,奇数长度的列表具有更大的第一个子列表

splitlist :: [a] -> Int -> ([a],[a])
splitlist [] = ([],[])
splitlist l@(x : xs) n | n > 0     = (x : ys, zs)
               | otherwise = (l, [])
    where (ys,zs) = splitlist xs (n - 1)

我知道我需要把签名改为[a] -〉([a],[a]),但是我应该把length(xs)之类的东西放在代码的什么地方,这样我就不会破坏递归了。

u91tlkcl

u91tlkcl1#

在真实的程序中,您可能应该使用

splitlist :: [a] -> ([a], [a])
splitlist xs = splitAt ((length xs + 1) `div` 2) xs

(i.e.沿着于dreamcrash的答案。)
但是,如果出于学习的目的,您正在寻找一个显式递归解决方案,请研究以下内容:

splitlist :: [a] -> ([a], [a])
splitlist xs = f xs xs where
    f (y : ys) (_ : _ : zs) =
        let (as, bs) = f ys zs
        in (y : as, bs)
    f (y : ys) (_ : []) = (y : [], ys)
    f ys [] = ([], ys)
n3h0vuf2

n3h0vuf22#

您可以使用take和drop来执行此操作:

splitlist :: [a] -> ([a],[a])
splitlist [] = ([],[])
splitlist l  = let half = (length(l) +1)`div` 2
               in (take half l, drop half l)

或者您可以利用函数splitAt:

splitlist list = splitAt ((length (list) + 1) `div` 2) list
pieyvz9o

pieyvz9o3#

你可以通过使用take和drop内置函数来实现这一点。但是如果你想用所有自己编写的函数来实现这一点,可以试试这个:

dropList :: Int -> [Int] -> [Int]
dropList 0 [] = []
dropList 0 (x:xs) = x:xs
dropList y [] = []
dropList y (x:xs) = dropList (y-1) xs

takeList :: Int -> [Int] -> [Int]
takeList 0 [] = []
takeList 0 (x:xs) = []
takeList y [] = []
takeList y (x:xs) 
  | y <= length (x:xs) =  x : takeList (y-1) xs
  | otherwise = []

split :: Int -> [Int] -> ([Int],[Int])
split 0 [] = ([],[])
split y [] = ([],[])
split y (x:xs) = (takeList y (x:xs), dropList y (x:xs))

main = do
  print (split 4 [1,2,3,4,5,6])

相关问题