我对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/

10-14 18:18
查看更多