如何在lapply中根据列表元素名称应用if条件语句
根据列表元素名称应用不同函数的解决方案
我确信这类问题已有多种提问方式,但仍未找到答案。我希望根据列表元素的名称,对列表应用不同的函数。
可复现示例
library(stringr) miniList <- list(apple = "I love apples", burger = "I like burgers", cherry = "I don't like cherries")
我的尝试代码
output <- lapply(miniList, FUN = function(miniList) { for(i in miniList) { if(str_detect(names(miniList[i]), "a")) { nameItem <- "a" } if(str_detect(names(miniList[i]), "b")) { nameItem <- "b" } if(str_detect(names(miniList[i]), "c")) { nameItem <- "c" } } if(str_detect(nameItem, "a")) { "alright" } if(str_detect(nameItem, "b")) { "better" } if(str_detect(nameItem, "c")) { "cool" } } )
报错信息
Error in if (str_detect(names(miniList[i]), "a")) { :
argument is of length zero
期望输出
> output [[1]] [1] "alright" [[2]] [1] "better" [[3]] [1] "cool"
问题分析
你的代码报错核心原因是**lapply遍历列表时,默认只传递列表的元素值,而不是元素名称**,所以在匿名函数里无法通过names(miniList[i])获取到元素名,自然会返回长度为0的对象,导致if判断报错。
解决方案
下面两种方法都能实现需求:
方法1:遍历列表名称
直接遍历列表的名称,通过名称索引元素,同时根据名称判断执行逻辑:
library(stringr) miniList <- list(apple = "I love apples", burger = "I like burgers", cherry = "I don't like cherries") output <- lapply(names(miniList), function(name) { if(str_detect(name, "a")) { "alright" } else if(str_detect(name, "b")) { "better" } else if(str_detect(name, "c")) { "cool" } })
方法2:用mapply同时传递元素和名称
mapply支持同时传入多个参数,这里把列表的元素值和名称一起传入函数,方便后续如果需要用到元素值的场景:
library(stringr) miniList <- list(apple = "I love apples", burger = "I like burgers", cherry = "I don't like cherries") output <- mapply(function(val, name) { # 若需要处理元素值val,可在此添加逻辑 if(str_detect(name, "a")) { "alright" } else if(str_detect(name, "b")) { "better" } else if(str_detect(name, "c")) { "cool" } }, miniList, names(miniList), SIMPLIFY = FALSE)
两种方法都能得到你期望的输出结果。
内容的提问来源于stack exchange,提问作者Sara
相关产品推荐
相关产品推荐

