Подтвердить что ты не робот

Есть ли эквивалент S4 для unlist()?

У меня есть опыт работы с объектами S4 и их слотами, поэтому я знаю, как обращаться к определенным слотам и подслоям. Я хотел бы узнать, как "де-сложить" объект таким образом, что unlist разделяет список S3.
Моя ближайшая цель - сопоставить S4 с одной из моих игрушек, которая возвращает количество элементов объекта:

lssize<-function(items){
            if (any(sapply(sapply(items,get),typeof)=='closure')){
        warning('Closures in list, will ignore.')
        items<-items[(sapply(sapply(bar,get),typeof)=='closure')!=TRUE]
    }
    sizes<-sapply(sapply(sapply(sapply(items,get,simplify=F), unlist,simplify=F), as.vector,simplify=F), length)
    return(sizes)
    }

(справедливо смеется мой код:-)). Я надеюсь, что не придется писать некоторую процедуру рекурсии, которая извлекает слоты по одному для их преобразования.

Изменить: я знаю, что object.size вернет bytecount; не то, что я здесь.

4b9b3361

Ответ 1

(Это исправлено, чтобы быть ближе к предыдущему удаленному ответу, используя slotName и slot вместо того, чтобы полагаться на attributes). Мы могли бы написать функцию, которая проверяет, является ли экземпляр объектом S4, и если он извлекает все слоты в виде списка и рекурсирует

f = function(x) {
    if (isS4(x)) {
        nms <- slotNames(x)
        names(nms) <- nms
        lapply(lapply(nms, slot, object=x), f)
    } else x
}

а затем

A = setClass("A", representation(x="numeric"))
B = setClass("B", representation(a="A", b="numeric"))
f(B())

чтобы получить простой старый список, который мы могли бы использовать в любых целях.

$a
$a$x
numeric(0)

$a$class
[1] "A"
attr(,"package")
[1] ".GlobalEnv"


$b
numeric(0)

$class
[1] "B"
attr(,"package")
[1] ".GlobalEnv"

f может потребоваться улучшить, например, для обработки значений NULL или классов S4, сделанных из классов S3, через setOldClass. Код validObject был бы моим выбором мест для поиска более полного обхода.

Обобщение может сделать посетителя по строкам

visitLeavesWith <-
    function(object, FUN, ...)
{
    f = function(x) {
        if (isS4(x)) {
            slots <- setNames(slotNames(x), slotNames(x))
            lapply(lapply(slots, slot, object=x), f)
        } else FUN(x, ...)
    }
    f(object)
}

например.

visitLeavesWith(B(), length)