P14 - 复制每个元素

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

P14 - 复制每个元素

Duplicate elements of a list

官方模块: Problems.P14 核心函数: dupli


← P13 直接实现游程编码 | P15 每个元素重复 N 次 →


题目描述

将列表中的每个元素复制一份,即每个元素在结果中连续出现两次。

函数签名

1dupli :: [a] -> [a]

思路

遍历列表,对每个元素输出两次:x : x : dupli xs

实现

方法一:递归

1dupli :: [a] -> [a]
2dupli []     = []
3dupli (x:xs) = x : x : dupli xs

最直接的递归,每个元素放两次。

方法二:concatMap

1dupli :: [a] -> [a]
2dupli = concatMap (\x -> [x, x])

或者更简洁地:

1dupli = concatMap (replicate 2)
concatMap 详解

concatMap f xs = concat (map f xs)——先 mapconcat,一步完成"映射并展平"。

拆解 concatMap (\x -> [x, x]) [1,2,3]

1第一步 map:  f 1 = [1,1]    f 2 = [2,2]    f 3 = [3,3]
2            → [[1,1], [2,2], [3,3]]
3
4第二步 concat: 拼接所有子列表 → [1,1,2,2,3,3]

所以 concatMap (\x -> [x, x]) 的意思是:对每个元素,生成一个包含该元素两次的小列表,再把所有小列表拼成一个大列表。

如果 duplimap 实现(忘记 concat):

1map (\x -> [x,x]) [1,2,3]    [[1,1],[2,2],[3,3]]  -- 类型是 [[Int]],不对

结果类型不对——map 返回的是列表的列表。concatMap 相当于 map 之后再 concat,一步到位把嵌套展平。

方法三:列表推导

1dupli xs = [x | x <- xs, _ <- [1, 2]]

_ <- [1, 2] 让每个 x 被取两次。

测试

1>>> dupli [1, 2, 3]
2[1,1,2,2,3,3]
3
4>>> dupli []
5[]
6
7>>> dupli "hi"
8"hhii"

参考


← P13 直接实现游程编码 | P15 每个元素重复 N 次 →