tidyverse(purrr包)中map、lmap、imap的区别是什么?
purrr包map/lmap/imap函数差异化说明(附R代码示例)
首先所有示例运行前需加载purrr包:library(purrr)
统一使用测试数据:test_vec <- c(a = 1, b = 2, c = 3)
核心差异总览
map():仅传入元素值到自定义函数,是最通用的迭代函数,行为等价于基础包lapply()lmap():传入长度为1的子列表到自定义函数,适合操作列表结构、保留/修改元素名的场景imap():同时传入元素值+元素索引/名称两个参数到自定义函数,是双参数迭代的语法糖
1. map() 基础迭代函数
适用于不需要用到元素位置、名称,仅对元素值本身做处理的场景
示例:将所有元素乘2
# .f每次接收的参数是单个数值 map(test_vec, ~ .x * 2)
返回结果
$a [1] 2 $b [1] 4 $c [1] 6
补充说明:如果需要返回指定类型的向量而非列表,可以使用带后缀的变体,比如map_dbl()返回双精度向量、map_chr()返回字符串向量,比基础包sapply()更稳定,不会自动做意外的格式转换。
2. lmap() 列表原子迭代函数
迭代单位是长度为1的子列表,而非单个元素值,输入如果是向量会被自动转为列表结构。自定义函数返回的所有子列表会被自动拼接为最终结果,支持单输入返回多元素。
示例:修改元素名同时计算新值
# .f每次接收的参数是长度为1的列表,比如第一次迭代的参数为 list(a = 1) lmap(test_vec, function(x) { old_name <- names(x) new_val <- x[[1]] * 10 # 返回自定义子列表,会被自动拼入最终结果 set_names(list(new_val), paste0(old_name, "_10x")) })
返回结果
$a_10x [1] 10 $b_10x [1] 20 $c_10x [1] 30
特殊用法:单输入返回多元素
# 每个输入对应返回2个元素,最终结果长度为输入的2倍 lmap(test_vec, ~ list(原值 = .x[[1]], 翻倍值 = .x[[1]] * 2))
3. imap() 带索引/名称的迭代函数
本质是
map2(x, names(x) %||% seq_along(x), .f)的语法糖,迭代时自动传入两个参数:第一个参数.x是元素值,第二个参数.y是元素的名称(如果输入有命名)或元素的位置序号(如果输入无命名),适合需要用到位置、名称做计算的场景。
示例:拼接元素名称与元素值
# .x为元素值,.y为元素名称 imap(test_vec, ~ paste0("元素", .y, "的取值为", .x))
返回结果
$a [1] "元素a的取值为1" $b [1] "元素b的取值为2" $c [1] "元素c的取值为3"
无命名输入的场景
no_name_vec <- c(10, 20, 30) # 此时.y自动替换为位置索引 imap(no_name_vec, ~ paste0("第", .y, "个元素的取值为", .x))
返回结果
[[1]] [1] "第1个元素的取值为10" [[2]] [1] "第2个元素的取值为20" [[3]] [1] "第3个元素的取值为30"
内容的提问来源于stack exchange,提问作者Hobbesian Thinker
相关产品推荐
相关产品推荐

