第九章:列表 List 数据类型

列表(List)是 R 语言中最灵活 的数据结构。与向量不同,列表可以存放不同类型的数据------数值、字符串、向量、甚至其他列表,统统可以放进去。在 R 实际开发中,很多函数的返回值都是列表。

一、为什么需要列表?

回顾一下向量的限制:

r 复制代码
# 向量只能存同类型,混合类型会自动转换
c(1, "hello", TRUE)
# → "1" "hello" "TRUE"  全变成了字符串!

列表打破了这个限制:

r 复制代码
list(1, "hello", TRUE, c(1, 2, 3))
# → 数值、字符串、逻辑值、向量,各就各位

二、创建列表

1. 基本创建

r 复制代码
student <- list(
  name = "张三",
  age = 20,
  scores = c(92, 85, 78),
  passed = TRUE
)

print(student)

运行结果:

txt 复制代码
$name
[1] "张三"

$age
[1] 20

$scores
[1] 92 85 78

$passed
[1] TRUE

2. 不命名也行

r 复制代码
info <- list("张三", 20, c(92, 85, 78))
print(info)

运行结果:

txt 复制代码
[[1]]
[1] "张三"

[[2]]
[1] 20

[[3]]
[1] 92 85 78

三、访问列表元素

列表有三种访问方式,必须搞清楚区别:

1. 用 $ 按名称访问(最常用)

r 复制代码
student <- list(name = "张三", age = 20, scores = c(92, 85, 78))

print(student$name)
print(student$scores)

运行结果:

txt 复制代码
[1] "张三"
[1] 92 85 78

2. 用 \["名称"] 访问

r 复制代码
student <- list(name = "张三", age = 20, scores = c(92, 85, 78))

print(student[["name"]])
print(student[["scores"]])

运行结果:

txt 复制代码
[1] "张三"
[1] 92 85 78

3. 用 \[索引] 按位置访问

r 复制代码
student <- list(name = "张三", age = 20, scores = c(92, 85, 78))

print(student[[1]])     # 第1个元素
print(student[[3]])     # 第3个元素

运行结果:

txt 复制代码
[1] "张三"
[1] 92 85 78

4. \[ ] 的区别(重点!)

r 复制代码
student <- list(name = "张三", age = 20)

# [[]] 取出的是元素本身
print(class(student[[1]]))     # "character"

# [] 取出的是子列表
print(class(student[1]))       # "list"
方式 返回类型 用途
list$name 元素本身 取单个元素
list[["name"]] 元素本身 取单个元素
list[[1]] 元素本身 按位置取元素
list[1] 子列表 取一个子列表
list[1:2] 子列表 取多个元素组成的子列表

简单记忆:一个括号 [ ] 切片,两个括号 [[ ]] 取值

四、修改列表元素

r 复制代码
student <- list(name = "张三", age = 20, scores = c(92, 85, 78))

# 修改元素
student$age <- 21
print(student$age)

# 修改向量中的某个值
student$scores[2] <- 90
print(student$scores)

# 添加新元素
student$gender <- "男"
print(student$gender)

# 删除元素(赋值为 NULL)
student$passed <- TRUE
student$passed <- NULL
print(student)

运行结果:

txt 复制代码
[1] 21
[1] 92 90 78
[1] "男"
$name
[1] "张三"

$age
[1] 21

$scores
[1] 92 90 78

$gender
[1] "男"

五、列表常用操作

1. 查看列表结构

r 复制代码
student <- list(name = "张三", age = 20, scores = c(92, 85, 78))

length(student)        # 元素个数 → 3
names(student)         # 所有元素名 → "name" "age" "scores"
str(student)           # 查看结构(调试常用)

str() 输出:

txt 复制代码
List of 3
 $ name  : chr "张三"
 $ age   : num 20
 $ scores: num [1:3] 92 85 78

2. 判断是否是列表

r 复制代码
student <- list(name = "张三")

is.list(student)       # TRUE
is.list(c(1, 2, 3))   # FALSE

3. 列表与向量互转

r 复制代码
# 向量 → 列表
v <- c(1, 2, 3)
lst <- as.list(v)
print(lst)

# 列表 → 向量(扁平化)
lst <- list(a = 1, b = 2, c = 3)
v <- unlist(lst)
print(v)

运行结果:

txt 复制代码
[[1]]
[1] 1

[[2]]
[1] 2

[[3]]
[1] 3

a b c
1 2 3

4. 合并列表

r 复制代码
part1 <- list(name = "张三", age = 20)
part2 <- list(city = "北京", school = "清华大学")

full <- c(part1, part2)
print(full)

运行结果:

txt 复制代码
$name
[1] "张三"

$age
[1] 20

$city
[1] "北京"

$school
[1] "清华大学"

六、遍历列表

1. 遍历值

r 复制代码
student <- list(name = "张三", age = 20, scores = c(92, 85, 78))

for (item in student) {
  print(item)
}

运行结果:

txt 复制代码
[1] "张三"
[1] 20
[1] 92 85 78

2. 同时遍历名称和值

r 复制代码
student <- list(name = "张三", age = 20, scores = c(92, 85, 78))

for (key in names(student)) {
  print(paste(key, ":", paste(student[[key]], collapse = ", ")))
}

运行结果:

txt 复制代码
[1] "name : 张三"
[1] "age : 20"
[1] "scores : 92, 85, 78"

3. 用 lapply 批量操作(推荐)

lapply 对列表每个元素应用一个函数,返回新列表:

r 复制代码
scores <- list(
  math = c(92, 85, 78),
  chinese = c(88, 72, 95),
  english = c(76, 90, 82)
)

# 计算每科平均分
averages <- lapply(scores, mean)
print(averages)

运行结果:

txt 复制代码
$math
[1] 85

$chinese
[1] 85

$english
[1] 82.6666666666667

lapply 是 R 函数式编程的精髓,比手写 for 循环更简洁。

七、嵌套列表(列表中套列表)

r 复制代码
class_info <- list(
  class_name = "高三一班",
  students = list(
    list(name = "张三", age = 18, score = 92),
    list(name = "李四", age = 19, score = 85),
    list(name = "王五", age = 18, score = 78)
  )
)

# 访问嵌套元素
print(class_info$class_name)
print(class_info$students[[1]]$name)
print(class_info$students[[2]]$score)

运行结果:

txt 复制代码
[1] "高三一班"
[1] "张三"
[1] 85

逐层剥洋葱:class_info → students → 第1个学生 → name

八、综合实战练习(可直接复制运行)

r 复制代码
# ==============================
# R 综合练习:列表实战
# 场景:学生信息管理系统
# ==============================

# 1. 创建多个学生信息(列表的列表)
students <- list(
  list(name = "张三", age = 20, scores = c(数学 = 92, 语文 = 85, 英语 = 78)),
  list(name = "李四", age = 21, scores = c(数学 = 88, 语文 = 72, 英语 = 90)),
  list(name = "王五", age = 19, scores = c(数学 = 76, 语文 = 95, 英语 = 82)),
  list(name = "赵六", age = 20, scores = c(数学 = 65, 语文 = 58, 英语 = 70)),
  list(name = "孙七", age = 22, scores = c(数学 = 95, 语文 = 88, 英语 = 92))
)

# 2. 遍历并打印每个学生的信息
print("=== 学生信息 ===")
for (i in 1:length(students)) {
  s <- students[[i]]
  avg <- mean(s$scores)
  print(paste(s$name, ",年龄", s$age, ",平均分", round(avg, 1)))
}

# 3. 找出平均分最高的学生
print("=== 最高平均分 ===")
max_avg <- 0
best_student <- ""
for (s in students) {
  avg <- mean(s$scores)
  if (avg > max_avg) {
    max_avg <- avg
    best_student <- s$name
  }
}
print(paste(best_student, ",平均分", round(max_avg, 1)))

# 4. 统计每科平均分(提取所有学生的各科成绩)
print("=== 各科平均分 ===")
subjects <- c("数学", "语文", "英语")
for (subj in subjects) {
  total <- 0
  for (s in students) {
    total <- total + s$scores[subj]
  }
  print(paste(subj, ":", round(total / length(students), 1)))
}

# 5. 找出有不及格科目的学生
print("=== 有不及格科目的学生 ===")
for (s in students) {
  if (any(s$scores < 60)) {
    failed <- names(s$scores[s$scores < 60])
    for (f in failed) {
      print(paste(s$name, "的", f, "不及格:", s$scores[f], "分"))
    }
  }
}

运行结果:

txt 复制代码
[1] "=== 学生信息 ==="
[1] "张三 ,年龄 20 ,平均分 85"
[1] "李四 ,年龄 21 ,平均分 83.3"
[1] "王五 ,年龄 19 ,平均分 84.3"
[1] "赵六 ,年龄 20 ,平均分 64.3"
[1] "孙七 ,年龄 22 ,平均分 91.7"
[1] "=== 最高平均分 ==="
[1] "孙七 ,平均分 91.7"
[1] "=== 各科平均分 ==="
[1] "数学 : 83.2"
[1] "语文 : 79.6"
[1] "英语 : 82.4"
[1] "=== 有不及格科目的学生 ==="
[1] "赵六 的 语文 不及格: 58 分"
相关推荐
起个破名想半天了15 小时前
算法与数据结构之Dijkstra算法
数据结构·dijkstra·单源最短路径·迪杰斯特拉算法
啦啦啦啦啦zzzz16 小时前
数据结构:哈夫曼编码
数据结构·c++·哈夫曼编码
ChillCoding16 小时前
更新中:C++ STL库,查找排序(基础算法),数据结构,数学算法,竞赛相关基础
数据结构·c++·算法
apcipot_rain17 小时前
计科八股20260606——二叉树、PCA、图深度学习、进程上下文、C语言预编译、文件读写、单精度浮点数
c语言·数据结构·算法·pca·图神经网络
落羽的落羽17 小时前
【项目】JsonRpc框架——开发实现2(业务层)
linux·数据结构·c++·人工智能·算法·json·动态规划
SHARK_pssm17 小时前
【数据结构——单链表】
数据结构·经验分享·笔记
lightqjx18 小时前
【算法】数据结构_并查集
数据结构·算法·并查集
dongf201918 小时前
R语言线性回归
数据分析·r语言·线性回归
小蒋学算法18 小时前
算法-掉落的方块-线段树
数据结构·算法
Brilliantwxx18 小时前
【算法从零到千】【8-15】滑动窗口
数据结构·算法