Доступ к элементу списка на основе значения атрибута - PullRequest
0 голосов
/ 10 мая 2018

Скажем, у меня есть список, элементы которого имеют атрибуты, как показано ниже:

my_list <- list()

my_list[[1]] <- 1:10
my_list[[2]] <- 11:20
my_list[[3]] <- 21:30

attr(my_list[[1]], "att1") <- "a"
attr(my_list[[2]], "att1") <- "b"
attr(my_list[[3]], "att1") <- "c"

attr(my_list[[1]], "att2") <- "1"
attr(my_list[[2]], "att2") <- "2"
attr(my_list[[3]], "att2") <- "3"

Теперь представьте, что в этом списке много сотен элементов, и я априори не знаю, какой элемент списка имеет нужные мне атрибуты. Но я знаю, что мне нужен элемент, скажем, att1 == "b" и att2 == "2" (но я не знаю, соответствует ли он элементу списка 2).

Есть ли способ в R посмотреть, какие элементы в списке имеют определенную комбинацию атрибутов?

Ответы [ 3 ]

0 голосов
/ 10 мая 2018

Хорошее решение (с четкой логикой ответа) уже предоставлено @Frank. Тем не менее, я подумал, чтобы охватить несколько других вариантов (опять же, уже @Frank в своем ответе намекнул).

Вариант № 1:

library(purrr)
my_list %>% keep(~ attr(., "att1") == "b" & attr(., "att2") == "2")

#[[1]]
# [1] 11 12 13 14 15 16 17 18 19 20
#attr(,"att1")
#[1] "b"
#attr(,"att2")
#[1] "2"

Вариант № 2: Использование sapply

my_list[sapply(my_list, function(x)attr(x, "att1") == "b" & attr(x, "att2") == "2")]
# [[1]]
# [1] 11 12 13 14 15 16 17 18 19 20
# attr(,"att1")
# [1] "b"
# attr(,"att2")
# [1] "2"
0 голосов
/ 10 мая 2018

Может быть это:

ls_attr <- sapply(my_list, attributes)
ls_attr
#     [,1] [,2] [,3]
# att1 "a"  "b"  "c" 
# att2 "1"  "2"  "3"

my_list[ apply(ls_attr, 2, function(x) all( x %in% c('b', '2') )) ]
# [[1]]
# [1] 11 12 13 14 15 16 17 18 19 20
# attr(,"att1")
# [1] "b"
# attr(,"att2")
# [1] "2"

Другое решение с несколькими атрибутами: нет ограничений на порядок атрибутов с этим кодом.

ls_attr <- sapply(my_list, attributes)
search_attr <- matrix( c( 'c', 'b', 2:3), ncol = nrow(ls_attr), byrow = TRUE )
my_list [ apply( matrix( ls_attr %in% search_attr, nrow = nrow(ls_attr), byrow = FALSE ), 2, all) ]
0 голосов
/ 10 мая 2018

Вы можете отфильтровать список с помощью Filter:

Filter(function(x) attr(x, "att1") == "b" & attr(x, "att2") == "2", my_list)

Если вы ожидаете, что элемент будет уникальным и хотите его выбрать, добавьте [[1]] в конце.


Лично я бы положил данные в таблицу:

library(data.table)
myDT = data.table(
  att1 = sapply(my_list, attr, "att1"), 
  att2 = sapply(my_list, attr, "att2"),
  data = my_list
)

#    att1 att2               data
# 1:    a    1       1,2,3,4,5,6,
# 2:    b    2 11,12,13,14,15,16,
# 3:    c    3 21,22,23,24,25,26,

Затем вы можете проверить, что att1 + att2 однозначно определяет элемент

nrow(myDT) == uniqueN(myDT, by=c("att1", "att2"))
# [1] TRUE

и написать вспомогательную функцию для поднабора

setkey(myDT, att1, att2)
get_element = function(a1, a2) myDT[.(a1, a2), data[[1]]]

get_element("b", "2")
#  [1] 11 12 13 14 15 16 17 18 19 20
# attr(,"att1")
# [1] "b"
# attr(,"att2")
# [1] "2"

Возможно, вы также захотите взглянуть на пакеты purrr и broom, которые предлагают различный синтаксис "tidyverse" для таблиц со столбцом списка.

...