列表推导式 #
一、列表推导式基础 #
1.1 什么是列表推导式 #
列表推导式是一种简洁的列表创建语法:
haskell
-- 基本形式
[表达式 | 生成器]
-- 示例
[x * 2 | x <- [1..5]] -- [2, 4, 6, 8, 10]
1.2 基本语法 #
haskell
-- 语法结构
[输出表达式 | 输入 <- 列表]
-- 示例
-- 创建平方列表
squares = [x * x | x <- [1..5]] -- [1, 4, 9, 16, 25]
-- 创建字符串列表
words = [x : "!" | x <- ["Hello", "World"]] -- ["Hello!", "World!"]
1.3 与map对比 #
haskell
-- 列表推导式
doubled = [x * 2 | x <- [1..5]]
-- 等价的map
doubled' = map (*2) [1..5]
二、生成器 #
2.1 单生成器 #
haskell
-- 单个生成器
[x | x <- [1..5]] -- [1, 2, 3, 4, 5]
-- 转换元素
[x + 1 | x <- [1..5]] -- [2, 3, 4, 5, 6]
-- 使用函数
[even x | x <- [1..5]] -- [False, True, False, True, False]
2.2 多生成器 #
haskell
-- 多个生成器(嵌套循环)
[(x, y) | x <- [1, 2], y <- ['a', 'b']]
-- [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]
-- 生成器顺序影响结果顺序
[show x ++ show y | x <- [1, 2], y <- [3, 4]]
-- ["13", "14", "23", "24"]
2.3 生成器依赖 #
haskell
-- 后面的生成器可以依赖前面的变量
[(x, y) | x <- [1..3], y <- [1..x]]
-- [(1, 1), (2, 1), (2, 2), (3, 1), (3, 2), (3, 3)]
-- 创建三角形坐标
triangles = [(x, y) | x <- [1..3], y <- [1..x]]
2.4 模式匹配生成器 #
haskell
-- 生成器中使用模式匹配
[x | (x, _) <- [(1, 'a'), (2, 'b'), (3, 'c')]]
-- [1, 2, 3]
-- 过滤不匹配的模式
[Just x | Just x <- [Just 1, Nothing, Just 2, Nothing, Just 3]]
-- [Just 1, Just 2, Just 3]
三、守卫 #
3.1 基本守卫 #
haskell
-- 守卫过滤元素
[x | x <- [1..10], even x] -- [2, 4, 6, 8, 10]
-- 与filter对比
[x | x <- [1..10], even x]
filter even [1..10] -- 等价
3.2 多守卫 #
haskell
-- 多个守卫条件
[x | x <- [1..20], x `mod` 2 == 0, x `mod` 3 == 0]
-- [6, 12, 18]
-- 等价于
[x | x <- [1..20], even x, x `mod` 3 == 0]
3.3 复杂守卫 #
haskell
-- 使用函数作为守卫
isPrime :: Int -> Bool
isPrime n = null [x | x <- [2..n-1], n `mod` x == 0]
-- 生成质数列表
primes = [x | x <- [2..50], isPrime x]
-- [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
-- 复杂条件
validPairs = [(x, y) | x <- [1..10], y <- [1..10], x < y, x + y > 10]
四、let绑定 #
4.1 let在列表推导式中 #
haskell
-- let定义局部变量
[x * y | x <- [1..5], let y = x * 2]
-- [2, 4, 6, 8, 10]
-- let定义多个变量
[a + b | x <- [1..5], let a = x * 2, let b = x + 1]
-- [3, 6, 9, 12, 15]
4.2 let与守卫结合 #
haskell
-- let定义后用于守卫
[x | x <- [1..20], let doubled = x * 2, doubled > 10]
-- [6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
-- 复杂计算
[result | x <- [1..10],
y <- [1..10],
let result = x * y,
result > 20]
五、嵌套推导式 #
5.1 嵌套列表推导式 #
haskell
-- 创建矩阵
matrix = [[x * y | y <- [1..3]] | x <- [1..3]]
-- [[1, 2, 3], [2, 4, 6], [3, 6, 9]]
-- 展平矩阵
flatten = [x | row <- matrix, x <- row]
-- [1, 2, 3, 2, 4, 6, 3, 6, 9]
5.2 多维推导 #
haskell
-- 三维坐标
coords3D = [(x, y, z) | x <- [0..1], y <- [0..1], z <- [0..1]]
-- [(0,0,0), (0,0,1), (0,1,0), (0,1,1), (1,0,0), (1,0,1), (1,1,0), (1,1,1)]
-- 排列组合
permutations = [(x, y, z) | x <- [1..3], y <- [1..3], z <- [1..3], x /= y, y /= z, x /= z]
5.3 嵌套与条件 #
haskell
-- 带条件的嵌套
validTriangles = [(a, b, c) |
a <- [1..10],
b <- [1..a],
c <- [1..b],
a + b > c,
a + c > b,
b + c > a]
六、并行推导 #
6.1 并行生成器 #
haskell
{-# LANGUAGE ParallelListComp #-}
-- 并行推导
[(x, y) | x <- [1..3] | y <- ['a'..'c']]
-- [(1, 'a'), (2, 'b'), (3, 'c')]
-- 等价于
zip [1..3] ['a'..'c']
6.2 使用zip代替 #
haskell
-- 不使用扩展
[(x, y) | (x, y) <- zip [1..3] ['a'..'c']]
-- [(1, 'a'), (2, 'b'), (3, 'c')]
七、实践示例 #
7.1 数学计算 #
haskell
-- 勾股数
pythagoreanTriples :: Int -> [(Int, Int, Int)]
pythagoreanTriples n =
[(a, b, c) |
a <- [1..n],
b <- [a..n],
c <- [b..n],
a^2 + b^2 == c^2]
-- 示例
pythagoreanTriples 20
-- [(3, 4, 5), (5, 12, 13), (6, 8, 10), (8, 15, 17), (9, 12, 15)]
-- 因子
factors :: Int -> [Int]
factors n = [x | x <- [1..n], n `mod` x == 0]
-- 完全数(等于其因子和的数)
perfectNumbers :: Int -> [Int]
perfectNumbers n = [x | x <- [1..n], sum (factors x) - x == x]
7.2 字符串处理 #
haskell
import Data.Char
-- 大写所有单词
uppercaseWords :: String -> [String]
uppercaseWords s = [map toUpper word | word <- words s]
-- 示例
uppercaseWords "hello world" -- ["HELLO", "WORLD"]
-- 提取数字
extractDigits :: String -> [Int]
extractDigits s = [digitToInt c | c <- s, isDigit c]
-- 统计字符
charCount :: String -> [(Char, Int)]
charCount s = [(c, length $ filter (== c) s) | c <- nub s]
where nub [] = []
nub (x:xs) = x : nub (filter (/= x) xs)
7.3 数据转换 #
haskell
-- 转换学生数据
type Student = (String, Int, Int) -- (name, math, english)
-- 获取及格学生
passingStudents :: [Student] -> [String]
passingStudents students =
[name | (name, math, eng) <- students, math >= 60, eng >= 60]
-- 计算平均分
averageScores :: [Student] -> [(String, Double)]
averageScores students =
[(name, fromIntegral (math + eng) / 2) | (name, math, eng) <- students]
-- 获取高分学生
topStudents :: [Student] -> [String]
topStudents students =
[name | (name, math, eng) <- students, let avg = (math + eng) / 2, avg >= 85]
7.4 排列组合 #
haskell
-- 全排列
permutations :: [a] -> [[a]]
permutations [] = [[]]
permutations xs = [x : ys | x <- xs, ys <- permutations (delete x xs)]
where delete _ [] = []
delete y (x:xs)
| x == y = xs
| otherwise = x : delete y xs
-- 组合
combinations :: Int -> [a] -> [[a]]
combinations 0 _ = [[]]
combinations _ [] = []
combinations n (x:xs) = [x:ys | ys <- combinations (n-1) xs] ++ combinations n xs
7.5 集合操作 #
haskell
-- 笛卡尔积
cartesian :: [a] -> [b] -> [(a, b)]
cartesian xs ys = [(x, y) | x <- xs, y <- ys]
-- 幂集
powerSet :: [a] -> [[a]]
powerSet [] = [[]]
powerSet (x:xs) = [x:ys | ys <- rest] ++ rest
where rest = powerSet xs
-- 示例
powerSet [1, 2]
-- [[1, 2], [1], [2], []]
八、性能考虑 #
8.1 列表推导式vs函数 #
haskell
-- 列表推导式
result1 = [x * 2 | x <- [1..1000000], even x]
-- 等价的函数组合
result2 = map (*2) $ filter even [1..1000000]
-- 性能相近,选择更可读的方式
8.2 避免重复计算 #
haskell
-- 不好:重复计算
bad = [expensive x | x <- xs, expensive x > 0]
-- 好:使用let
good = [result | x <- xs, let result = expensive x, result > 0]
九、最佳实践 #
9.1 可读性 #
haskell
-- 好:简单的列表推导式
squares = [x * x | x <- [1..10]]
-- 复杂逻辑使用函数
processStudents students =
[format name avg |
(name, math, eng) <- students,
let avg = (math + eng) / 2,
avg >= 60]
where
format name avg = name ++ ": " ++ show avg
9.2 选择合适的方式 #
haskell
-- 简单转换:使用map
doubled = map (*2) [1..10]
-- 简单过滤:使用filter
evens = filter even [1..10]
-- 复杂逻辑:使用列表推导式
complex = [x * y | x <- [1..10], y <- [1..x], even (x + y)]
十、总结 #
列表推导式要点:
- 基本语法:
[表达式 | 生成器] - 生成器:
x <- 列表从列表取值 - 多生成器:相当于嵌套循环
- 守卫:过滤满足条件的元素
- let绑定:定义局部变量
- 嵌套推导:创建多维结构
- 实践应用:数学计算、字符串处理、数据转换
掌握列表推导式后,让我们继续学习列表函数。
最后更新:2026-03-27