P20 - 删除第 k 个元素

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

P20 - 删除第 k 个元素

Remove the K’th element from a list

官方模块: Problems.P20 核心函数: removeAt


← P19 旋转列表 N 位 | P21 在指定位置插入元素 →


题目描述

删除列表中第 k 个元素(1-based indexing)。返回被删除的元素和剩余列表组成的元组。

函数签名

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

注意:k 是第一个参数,列表是第二个参数。

思路

splitAt 在 k-1 处切分:

实现

方法一:splitAt

1removeAt :: Int -> [a] -> (a, [a])
2removeAt k xs = let (left, right) = splitAt (k - 1) xs
3                in (head right, left ++ tail right)

splitAt (k-1) xs 在目标位置前切分。head right 是被删除的元素,left ++ tail right 是剩余列表。

注意:这个实现假设 k 在合法范围内。如果 k > 列表长度,head right 会抛异常。

方法二:递归

1removeAt :: Int -> [a] -> (a, [a])
2removeAt 1 (x:xs) = (x, xs)
3removeAt n (x:xs) = let (removed, rest) = removeAt (n - 1) xs
4                    in (removed, x : rest)

模式匹配 1 (x:xs) 命中目标——删除 x,剩余 xs。否则递归前进。

方法三:带 Maybe 的安全版本(扩展)

官方签名不要求安全处理,但如果想避免异常:

1removeAtSafe :: Int -> [a] -> Maybe (a, [a])
2removeAtSafe _ [] = Nothing
3removeAtSafe 1 (x:xs) = Just (x, xs)
4removeAtSafe n (x:xs)
5  | n > 1     = (\(r, rest) -> (r, x : rest)) <$> removeAtSafe (n - 1) xs
6  | otherwise = Nothing

示例:用 removeAt 实现其他操作

removeAt 是列表操作的基础构建块:

1-- 删除第 k 个(只返回剩余列表)
2deleteAt k xs = snd (removeAt k xs)
3
4-- 提取第 k 个(只返回元素)
5extractAt k xs = fst (removeAt k xs)

测试

1>>> removeAt 2 "abcd"
2('b', "acd")
3
4>>> removeAt 1 [10, 20, 30]
5(10, [20, 30])
6
7>>> removeAt 3 [1, 2, 3]
8(3, [1, 2])

参考


← P19 旋转列表 N 位 | P21 在指定位置插入元素 →