我对Haskell来说还很陌生,并且遇到了一些麻烦。我正在尝试实现一个需要一个列表和一个int的函数。 int应该是将列表分为一对列表的索引k。第一个包含列表的前k个元素,第二个从k + 1到最后一个元素。这是我到目前为止的内容:
split :: [a] -> Int -> ([a], [a])
split [] k = error "Empty list!"
split (x:[]) k = ([x],[])
split xs k | k >= (length xs) = error "Number out of range!"
| k < 0 = error "Number out of range!"
我实际上无法弄清楚如何进行拆分。任何帮助,将不胜感激。
最佳答案
首先,请注意,您要构造的函数已经在标准库Prelude
中-称为splitAt
。现在,直接看一下它的定义是令人困惑的,因为有两种算法,一种根本不使用标准的递归结构-splitAt n xs = (take n xs, drop n xs)
-另一种是经过手动优化使其丑陋的算法。前者具有更直观的意义,因为您只需将前缀和后缀放在一对即可。但是,后者的教学内容更多,并具有以下总体结构:
splitAt :: Int -> [a] -> ([a], [a])
splitAt 0 xs = ([], xs)
splitAt _ [] = ([], [])
splitAt n (x:xs) = (x:xs', xs'')
where
(xs', xs'') = splitAt (n - 1) xs
基本思想是,如果列表由头和尾组成(形式为
x:xs
),则从索引k + 1开始的列表与从k开始的列表相同。第一个元素-drop (k + 1) (x : xs) == drop k xs
。要构造前缀,您可以类似地删除第一个元素,采用较小的前缀,然后将元素粘贴回take (k + 1) (x : xs) == x : take k xs
上。关于list - Haskell:将索引k的列表分成2个,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12540078/