在嵌套列表中查找匹配项的索引位置

13

我想找到嵌套列表和目标值(11)的匹配索引。

数据:

f <- list(
  list(1, 2, 3),
  list(4, 5, list(8, list(11, 12)))
)

目标值为11时的期望输出结果:

c(2, 3, 2, 1)

印刷:

 f
[[1]]
[[1]][[1]]
[1] 1

[[1]][[2]]
[1] 2

[[1]][[3]]
[1] 3


[[2]]
[[2]][[1]]
[1] 4

[[2]][[2]]
[1] 5

[[2]][[3]]
[[2]][[3]][[1]]
[1] 8

[[2]][[3]][[2]]
--->>>  [[2]][[3]][[2]][[1]]  <<<----
-->>>> [1] 11 <<<----

[[2]][[3]][[2]][[2]]
[1] 12

我的尝试:

使用unlist(data)匹配,在which()中查找参数并查看arrInd()

我想避免在R中运行多个for循环。最好在C、C++等中完成所有循环。在自己实现之前,我想要检查是否缺少某个函数。

4个回答

7
您可以尝试使用reshape2中的melt()函数:
melted_lst <- reshape2::melt(f) 
melted_lst[sort(colnames(melted_lst))][melted_lst$value == 11, ]

  L1 L2 L3 L4 value
7  2  3  2  1    11

或者使用data.table中的melt()函数(正如@IceCreamToucan所提到的):

melted_lst <- data.table::melt(f)
melted_lst[sort(colnames(melted_lst))][melted_lst$value == 11, ]

1
s[,order(names(s))][s$value==11,] - Onyambu

2

使用rrapply包中的rrapply也可以完成此操作(这是基础rapply的扩展版本)。condition参数决定应将f应用到哪些元素上,f函数中的.xpos参数评估嵌套列表中元素的位置。 how = "flatten"会丢弃所有不满足condition的列表元素并返回一个平坦的列表:

library(rrapply)

rrapply(f, condition = function(x) x == 11, f = function(x, .xpos) .xpos, how = "flatten")
#> [[1]]
#> [1] 2 3 2 1

2
foo = function(x, sep = ".") {
    names(x) = paste0(seq_along(x))
    while(any(sapply(x, class) == "list")) {
        ind = sapply(x, class) == "list"
        temp = unlist(x[ind], recursive = FALSE)
        names(temp) = paste0(rep(names(x)[ind], lengths(x[ind])),
                             sep,
                             sequence(lengths(x[ind])))
        x = c(x[!ind], temp)
    }
    return(x)
}
f2 = foo(f)
names(which(unlist(f2) == 11))
#[1] "2.3.2.1"

很好,对于我遇到的某些情况,这个解决方案在数据结构方面似乎更加健壮。 - Tlatwork

1
另一种使用 tibble::enframe() 的方法:

library(tidyverse)
f <- list(
  list(1, 2, 3),
  list(4, 5, list(8, list(11, 12)))
)

df <- enframe(f)
while(!all(lengths(df$value)==1)) df <- df %>% 
  mutate(value = map(value,~enframe(.) %>% mutate_at("value", as.list))) %>%
  unnest(value)
df <- df %>% unnest(value)
df
#> # A tibble: 8 x 5
#>    name name1 name2 name3 value
#>   <int> <int> <int> <int> <dbl>
#> 1     1     1     1     1     1
#> 2     1     2     1     1     2
#> 3     1     3     1     1     3
#> 4     2     1     1     1     4
#> 5     2     2     1     1     5
#> 6     2     3     1     1     8
#> 7     2     3     2     1    11
#> 8     2     3     2     2    12

filter(df, value == 11) %>%
  select(-value) %>%
  unlist(use.names = F)
#> [1] 2 3 2 1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接