如何从列表中删除元素?

How can I remove an element from a list?

提问人:David Locke 提问时间:3/17/2009 最后编辑:KimDavid Locke 更新时间:11/3/2023 访问量:667093

问:

我有一个列表,我想从中删除一个元素。我该怎么做?

我试着在参考手册中查找我认为此功能的明显名称,但我没有找到任何合适的内容。

列表 索引 R-FAQ

评论

0赞 smci 8/23/2018
取决于您是要按值删除它,例如“值 5”,还是按索引/索引“索引 5 处的元素”或“索引处的元素 c(5:6,10)”?如果要按值删除并且存在重复项,则是要仅删除重复项、第一次或最后一次出现,还是全部删除?是否保证列表包含您的元素/索引?我们需要处理列表为空的情况吗?我们是否需要确保 NA 通过(/排除)?列表是保证扁平的还是可以嵌套的?后来有多少深度?
5赞 JStrahl 9/19/2018
setdiff(myList,elementToRemove)

答:

251赞 Chad Birch 3/17/2009 #1

我根本不了解 R,但一些创造性的谷歌搜索将我带到了这里:http://tolstoy.newcastle.edu.au/R/help/05/04/1919.html

那里的关键引述:

我没有找到关于如何从列表中删除元素的 R 明确文档,但反复试验告诉我

myList[[5]] <- NULL

将删除第 5 个元素,然后“关闭”因删除该元素而导致的孔。这充斥着索引值,所以我在删除元素时必须小心。我必须从列表的后面工作到前面。

稍后在线程中对该帖子的回复指出:

若要删除列表的元素,请参阅 R 常见问题解答 7.1

R FAQ 的相关部分说:

...不要将 x[i] 或 x[[i]] 设置为 NULL,因为这会从列表中删除相应的组件。

这似乎告诉您(以一种有点倒退的方式)如何删除元素。

评论

8赞 David Locke 3/17/2009
谢谢,mylist[i] < - NULL 正是做到这一点的方法。
47赞 wfbarksdale 10/5/2011
这对我不起作用。我得到:Error in list[length(list)] <- NULL : replacement has length zero
5赞 wfbarksdale 10/5/2011
@Aleksandr Levchuck 的帖子向我展示了我实际上正在处理一个向量,需要创建一个新对象
0赞 Josh 5/21/2021
这是一个很好的捷径,但在我看来,@Kim的答案是删除列表元素的“正确”方法,因为它允许使用字符串来识别列表元素,可以同时删除多个元素,并且不需要就地完成。我是否遗漏了什么(除了 OP 的问题是关于删除单个元素的事实)?谢谢。within
294赞 Florian Jenn 3/25/2009 #2

如果您不想就地修改列表(例如,将删除元素的列表传递给函数),则可以使用索引:负索引表示“不包含此元素”。

x <- list("a", "b", "c", "d", "e")  # example list

x[-2]        # without 2nd element

x[-c(2, 3)]  # without 2nd and 3rd

此外,逻辑索引向量也很有用:

x[x != "b"]  # without elements that are "b"

这也适用于数据帧:

df <- data.frame(number = 1:5, name = letters[1:5])

df[df$name != "b", ]      # rows without "b"

df[df$number %% 2 == 1, ] # rows with odd numbers only

评论

8赞 Carl Witthoft 1/31/2018
仅当列表元素中有单个项目“b”时,逻辑索引才起作用。你不能以这种方式删除 ,也不能从列表元素中删除 “b” 。x$bx[[2]] = c("b","k")
0赞 Florian Jenn 8/17/2018
关于单个项目与多个项目:可用于针对多个项目进行测试。我不确定你说的“不能删除 x$b”是什么意思——你的意思是删除整个列吗?%in%b
23赞 Sukhi 7/27/2010 #3

从单行列表中删除 Null 元素:

x=x[-(which(sapply(x,is.null),arr.ind=TRUE))]

干杯

评论

3赞 Richie Cotton 1/8/2014
此代码在为空列表时中断。请改用 from 执行此任务。xcompactplyr
0赞 user3055034 9/30/2015
此外,如果列表中没有 null,则返回将完全删除该行。-(which(sapply(x,is.null),arr.ind=TRUE))named integer(0)
40赞 Aleksandr Levchuk 1/14/2011 #4

以下是在 R 中删除列表的最后一个元素的方法:

x <- list("a", "b", "c", "d", "e")
x[length(x)] <- NULL

如果 x 可能是一个向量,那么你需要创建一个新对象:

x <- c("a", "b", "c", "d", "e")
x <- x[-length(x)]
  • 处理列表向量

评论

0赞 Dan Barowy 8/5/2014
@krlmlr:相反,这个解决方案比 Florian 的答案更通用,因为它在集合类型中是多态的。
0赞 krlmlr 8/6/2014
@DanBarowy:我错了:这似乎是乍得的答案(公认的答案)和弗洛里安的答案的综合。不过,这是一个很好的简短总结。
-1赞 Pavidus 11/16/2012 #5

您可以使用 .which

x<-c(1:5)
x
#[1] 1 2 3 4 5
x<-x[-which(x==4)]
x
#[1] 1 2 3 5
19赞 alko989 2/26/2014 #6

如果您有一个命名列表,并且想要删除特定元素,您可以尝试:

lst <- list(a = 1:4, b = 4:8, c = 8:10)

if("b" %in% names(lst)) lst <- lst[ - which(names(lst) == "b")]

这将创建一个包含元素 , , .第二行在检查元素是否存在后删除元素(以避免@hjv提到的问题)。lstabcb

或更好:

lst$b <- NULL

这样,尝试删除不存在的元素(例如lst$g <- NULL)

11赞 user2030503 10/25/2014 #7

有 rlist 包 (http://cran.r-project.org/web/packages/rlist/index.html) 来处理各种列表操作。

示例 (http://cran.r-project.org/web/packages/rlist/vignettes/Filtering.html):

library(rlist)
devs <- 
  list(
    p1=list(name="Ken",age=24,
      interest=c("reading","music","movies"),
      lang=list(r=2,csharp=4,python=3)),
    p2=list(name="James",age=25,
      interest=c("sports","music"),
      lang=list(r=3,java=2,cpp=5)),
    p3=list(name="Penny",age=24,
      interest=c("movies","reading"),
      lang=list(r=1,cpp=4,python=2)))

list.remove(devs, c("p1","p2"))

结果:

# $p3
# $p3$name
# [1] "Penny"
# 
# $p3$age
# [1] 24
# 
# $p3$interest
# [1] "movies"  "reading"
# 
# $p3$lang
# $p3$lang$r
# [1] 1
# 
# $p3$lang$cpp
# [1] 4
# 
# $p3$lang$python
# [1] 2

评论

0赞 Arthur Yip 2/20/2019
如何删除此示例中的 Python 或 Lang 项?
9赞 user2035799 6/10/2015 #8

不知道你是否还需要这个问题的答案,但我从我有限的(3 周的自学 R)经验中发现,使用赋值实际上是错误的或次优的,特别是如果你在类似 for 循环中动态更新列表。NULL

更准确地说,使用

myList[[5]] <- NULL

将抛出错误

myList[[5]] <- NULL : 替换的长度为零

供应的元件多于要更换的元件

我发现更一致的工作是

myList <- myList[[-5]]

评论

2赞 n1k31t4 1/6/2016
好答案!但是,我认为应该是单方括号,否则您只会取消选择该列表元素的内容,而不是元素本身。好吧,至少使用双方括号会给我这个错误:“尝试选择多个元素”。当时对我有用的是:.[[-5]]myList <- myList[-5]
-1赞 RocketRon 7/2/2015 #9

这个怎么样?同样,使用索引

> m <- c(1:5)
> m
[1] 1 2 3 4 5

> m[1:length(m)-1]
[1] 1 2 3 4

> m[-(length(m))]
[1] 1 2 3 4

评论

1赞 C8H10N4O2 7/2/2015
m 是向量,而不是列表
1赞 Gregor Thomas 7/8/2015
该方法确实适用于列表,但 OP 很幸运,可能想要更多的括号:m[1:(length(m) - 1)]
7赞 Alexey Shiklomanov 4/28/2017 #10

只是想快速添加(因为我没有在任何答案中看到它)对于命名列表,您也可以这样做.例如:l["name"] <- NULL

l <- list(a = 1, b = 2, cc = 3)
l['b'] <- NULL
2赞 Ferroao 8/26/2017 #11

使用 lapply 和 grep:

lst <- list(a = 1:4, b = 4:8, c = 8:10)
# say you want to remove a and c
toremove<-c("a","c")
lstnew<-lst[-unlist(lapply(toremove, function(x) grep(x, names(lst)) ) ) ]
# or
pattern<-"a|c"
lstnew<-lst[-grep(pattern, names(lst))]
# or
lst %>% purrr::discard(names(.) == "a") # use %in% for a set

评论

0赞 robertspierre 7/23/2023
感谢您使用 Tidyverse 的解决方案!
3赞 DJJ 1/11/2018 #12

对于命名列表,我发现这些辅助函数很有用

member <- function(list,names){
    ## return the elements of the list with the input names
    member..names <- names(list)
    index <- which(member..names %in% names)
    list[index]    
}


exclude <- function(list,names){
     ## return the elements of the list not belonging to names
     member..names <- names(list)
     index <- which(!(member..names %in% names))
    list[index]    
}  
aa <- structure(list(a = 1:10, b = 4:5, fruits = c("apple", "orange"
)), .Names = c("a", "b", "fruits"))

> aa
## $a
##  [1]  1  2  3  4  5  6  7  8  9 10

## $b
## [1] 4 5

## $fruits
## [1] "apple"  "orange"


> member(aa,"fruits")
## $fruits
## [1] "apple"  "orange"


> exclude(aa,"fruits")
## $a
##  [1]  1  2  3  4  5  6  7  8  9 10

## $b
## [1] 4 5
66赞 Kim 5/3/2018 #13

我想补充一点,如果它是一个命名列表,您可以简单地使用 .within

l <- list(a = 1, b = 2)    
> within(l, rm(a))
$b
[1] 2

因此,您可以覆盖原始列表

l <- within(l, rm(a)) 

从列表中删除名为 的元素。al

评论

7赞 Vlad 11/26/2019
做多个within(l, rm(a, b))
5赞 José 4/9/2021
要从字符向量执行多个操作:x <- c("a","b"); within(l,rm(list=x))
16赞 Sowmya S. Manian 9/10/2018 #14

使用(负号)和元素的位置,例如,如果要删除第三个元素,请将其用作-your_list[-3]

输入

my_list <- list(a = 3, b = 3, c = 4, d = "Hello", e = NA)
my_list
# $`a`
# [1] 3

# $b
# [1] 3

# $c
# [1] 4

# $d
# [1] "Hello"

# $e
# [1] NA

从列表中删除单个元素

 my_list[-3]
 # $`a`
 # [1] 3

 # $b
 # [1] 3

 # $d
 # [1] "Hello"

 # $e
 [1] NA

从列表中删除多个元素

 my_list[c(-1,-3,-2)]
 # $`d`
 # [1] "Hello"

 # $e
 # [1] NA

 my_list[c(-3:-5)]
 # $`a`
 # [1] 3

 # $b
 # [1] 3

 my_list[-seq(1:2)]
 # $`c`
 # [1] 4

 # $d
 # [1] "Hello"

 # $e
 # [1] NA
-1赞 Greg Minshall 10/27/2018 #15

如果您想避免使用数字索引,可以使用

a <- setdiff(names(a),c("name1", ..., "namen"))

从 a 中删除名称。这适用于列表namea...namen

> l <- list(a=1,b=2)
> l[setdiff(names(l),"a")]
$b
[1] 2

以及载体

> v <- c(a=1,b=2)
> v[setdiff(names(v),"a")]
b 
2
2赞 Roasty247 7/24/2020 #16

还可以使用包的功能从列表中负索引以删除列表项。extractmagrittr

a <- seq(1,5)
b <- seq(2,6)
c <- seq(3,7)
l <- list(a,b,c)

library(magrittr)

extract(l,-1) #simple one-function method
[[1]]
[1] 2 3 4 5 6

[[2]]
[1] 3 4 5 6 7
0赞 arranjdavis 7/20/2021 #17

这是一个可以使用基础 R 完成的简单解决方案。它从原始数字列表中删除数字 5。您可以使用相同的方法从列表中删除所需的任何元素。

#the original list
original_list = c(1:10)

#the list element to remove
remove = 5

#the new list (which will not contain whatever the `remove` variable equals)
new_list = c()

#go through all the elements in the list and add them to the new list if they don't equal the `remove` variable
counter = 1
for (n in original_list){
  if (n != ){
    new_list[[counter]] = n
    counter = counter + 1
  }
}

该变量不再包含 5。new_list

new_list
# [1]  1  2  3  4  6  7  8  9 10
1赞 LMc 2/2/2022 #18

包中有几个选项未提及:purrr

pluck并且适用于嵌套值,您可以使用名称和/或索引的组合来访问它:assign_in

library(purrr)

l <- list("a" = 1:2, "b" = 3:4, "d" = list("e" = 5:6, "f" = 7:8))

# select values (by name and/or index)
all.equal(pluck(l, "d", "e"), pluck(l, 3, "e"), pluck(l, 3, 1))
[1] TRUE

# or if element location stored in a vector use !!!
pluck(l, !!! as.list(c("d", "e")))
[1] 5 6

# remove values (modifies in place)
pluck(l, "d", "e") <- NULL

# assign_in to remove values with name and/or index (does not modify in place)
assign_in(l, list("d", 1), NULL)
$a
[1] 1 2

$b
[1] 3 4

$d
$d$f
[1] 7 8

或者,您可以使用赋值 或 :modify_listzap()NULL

all.equal(list_modify(l, a = zap()), list_modify(l, a = NULL))
[1] TRUE

您可以使用带有 和 的谓词函数删除或保留元素:discardkeep

# remove numeric elements
discard(l, is.numeric)
$d
$d$e
[1] 5 6

$d$f
[1] 7 8

# keep numeric elements
keep(l, is.numeric)
$a
[1] 1 2

$b
[1] 3 4

评论

0赞 RAFisherman 3/29/2022
pluck(l, "d", "e") <- NULL为我工作。我尝试过摆脱类似的东西,但在我闪亮的应用程序中,我得到了.您的语句实际上删除了该值。谢谢!names(list(a = 1, b = 2, c = 3)[c("b", "c")])aNA, b, cplucka
0赞 LMc 3/29/2022
@captinbo我不清楚你想做什么。 返回。如果您尝试删除,则可以分配它,或选择其他不是 的元素。names(list(a = 1, b = 2, c = 3)[c("b", "c")])"b" "c"aNULLa
0赞 RAFisherman 3/30/2022
是的,它返回“b”、“c”,这就是我正在尝试做的。但奇怪的是,在我的 R Shiny 应用程序中,它在运行时返回。我花了一个小时来研究这个错误,尝试不同的方法来将我的列表子集到我想要的元素,但只有你的方法有效。很奇怪的是,我得到了一个带有名字的列表。"NA", "b", "c"pluckNA
0赞 LMc 3/31/2022
@captinbo,如果您可以制作一个小的可重现示例并发布它,这将是一个很好的 SO 问题。
2赞 Peter 4/29/2023 #19

如果您只想删除元素的第一个匹配项并保留其余元素"b"

x <- c("a", "b", "b", "c", "d", "e")

which(x == "b")
# [1] 2 3

which(x == "b")[1]
# [1] 2

x[-which(x == "b")[1]]
# [1] "a" "b" "c" "d" "e"

评论

0赞 skoz 10/6/2023
仅当列表包含“b”项时,这才有效
0赞 Ali 11/3/2023 #20

假设“remove”意味着在不更改整体顺序的情况下将其设置为“NULL”。

mylist <- list("a", "b", "c", "d", "e", "f", "g")

# remove rule (or)
# 1. remove letter "e" & "f"
# 2. remove the 2nd value

mapply(
  \(x, y) if (x %in% c("e", "f") | y == 2) { NULL } else { x },
  mylist,
  1:length(mylist)
)

# output:
# [[1]]
# [1] "a"
# 
# [[2]]
# NULL
# 
# [[3]]
# [1] "c"
# 
# [[4]]
# [1] "d"
# 
# [[5]]
# NULL
# 
# [[6]]
# NULL
# 
# [[7]]
# [1] "g"