P17 - 在 N 处切分列表

2026-09-07 00:00    #Haskell   #99题   #列表  

P17 - 在 N 处切分列表

Split a list into two parts

官方模块: Problems.P17 核心函数: split


← P16 每隔 N 个删除一个元素 | P18 提取子列表 →


题目描述

在指定的位置 N 处将列表切分为两个子列表。前一部分包含前 N 个元素,后一部分包含剩余元素。

函数签名

1split :: [a] -> Int -> ([a], [a])

思路

实现

方法一:take + drop

1split :: [a] -> Int -> ([a], [a])
2split xs n = (take n xs, drop n xs)

标准库 splitAt 做的就是这件事,这就是它的实现方式。

如果 N 大于列表长度,take 返回整个列表,drop 返回空列表,行为安全。

方法二:递归

1split :: [a] -> Int -> ([a], [a])
2split xs 0 = ([], xs)
3split [] _ = ([], [])
4split (x:xs) n = let (first, second) = split xs (n - 1)
5                 in (x : first, second)

不用 take/drop,纯递归实现。N 递减到 0 时停止取元素。

方法三:使用标准库

1import Data.List (splitAt)
2
3split :: [a] -> Int -> ([a], [a])
4split = splitAt

标准库的 splitAt 就是 P17 的官方解法。

splitAt 的关系

实际上 P17 的 split 就是标准库 splitAt 的重新实现。splitAtGHC.List 中的定义就是:

1splitAt n xs = (take n xs, drop n xs)

测试

1>>> split "abcdefghik" 3
2("abc","defghik")
3
4>>> split [1,2,3] 5
5([1,2,3],[])
6
7>>> split [] 3
8([],[])

参考


← P16 每隔 N 个删除一个元素 | P18 提取子列表 →