第九章:列表 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 分"
相关推荐
m0_547486661 小时前
郑州轻工业大学《数据结构》期末试卷及答案2018-2022学年(AB卷)
数据结构·期末试卷·郑州轻工业大学
变量未定义~1 小时前
字符串哈希匹配字符串
数据结构·算法·哈希算法
bnmoel2 小时前
数据结构深度剖析栈与队列:结构、边界实现与进出操作全解析
c语言·数据结构·算法··队列
ChoSeitaku2 小时前
06_可变参数_递归_类和对象_封装
java·数据结构·算法
图码2 小时前
文本两端对齐算法详解:从LeetCode到实际应用
数据结构·图像处理·算法·leetcode·生成对抗网络·面试·职场和发展
liu****2 小时前
第16届国赛蓝桥杯大赛C/C++大学C组
c语言·数据结构·c++·算法·蓝桥杯
雁迟2 小时前
第十章:数据框 DataFrame(数据分析主力)
数据挖掘·数据分析·r语言
代码无bug抓狂人2 小时前
用回溯算法解决01背包
数据结构·算法
Odedipus2 小时前
二叉树的学习笔记
数据结构·笔记·学习