Найти позицию индекса во вложенных списках для совпадения
Я хочу найти индексы соответствия вложенного списка и целевого значения (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()
.
Я бы не использовал многократные циклы for в R. Лучше было бы делать все циклы в C, C++,... Перед тем, как реализовывать это самостоятельно, я хотел проверить, не пропускаю ли функцию.
Ответы
Ответ 1
Вы можете попробовать melt()
из reshape2
:
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
Или с melt()
из data.table
(как упомянуто @IceCreamToucan):
melted_lst <- data.table::melt(f)
melted_lst[sort(colnames(melted_lst))][melted_lst$value == 11, ]
Ответ 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"
Ответ 3
Еще один дубль с использованием 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