2013-02-10 24 views
12

Mam pewne doświadczenie w pracy z obiektami S4 i ich gniazdami, więc wiem, jak uzyskać dostęp do konkretnych gniazd i pod-slotów. Chciałbym się nauczyć, jak "rozdzielić" obiekt w taki sposób, aby unlist rozebrał listę na S3.
Moja bezpośrednim celem jest mieć odpowiednika S4 do jednego z moich zabawek, które zwraca liczbę elementów obiektu:Czy istnieje odpowiednik S4 dla opcji unlist()?

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) 
    } 

(bez targach śmieje się mój kod :-)). Mam nadzieję, że nie będę musiał pisać rutyny rekurencyjnej, która wyodrębnia automaty po jednym na raz, aby je konwertować.

Edytuj: Wiem, że object.size zwróci wartość z bajtów; nie to, po co tu jestem.

+1

Czasami warto spojrzeć na 'str()' ('utils ::: str .default' really) - zarówno jego wyniki, gdy są stosowane do obiektów S4, jak i kod używany do przechodzenia przez wszystkie sloty obiektu S4. –

Odpowiedz

9

(Zostało to zmienione tak, aby było bliższe poprzedniej, skasowanej odpowiedzi, przy użyciu slotName i slot zamiast polegania na attributes). może napisać funkcję, która sprawdza, czy przykład celem S4, a jeśli tak, to wyciąga wszystkie boksy jak liście i recurses

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

a następnie

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

do osiągnięcia zwykłego starej listy które moglibyśmy wykorzystać do dowolnych celów.

$a 
$a$x 
numeric(0) 

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


$b 
numeric(0) 

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

f konieczne może być zwiększona, na przykład do obsługi wartości NULL lub klasy S4 wykonane z klas S3 poprzez setOldClass. Kod do validObject byłby moim wyborem miejsc do poszukiwania bardziej wszechstronnego przejścia.

Uogólnienie może wykonać użytkownik, wzdłuż linii

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) 
} 

np

visitLeavesWith(B(), length) 
+0

To ładnie wygląda - dobre wzmocnienie (usuniętej) innej odpowiedzi. Tak, prawdopodobnie powinienem "przekonwertować" na rozmiary raportów obiektów w bajtach, a nie jak na liczniki elementów :-) –

+0

Mogę ci tylko raz powiedzieć :-). Dziękuję za poświęcenie czasu na zebranie kodu. Dam ci pełny kredyt, gdy (jeśli) zbuduję pakiet narzędzi pomocniczych, które zawierają 'lssize'. –

+0

BTW, więc przypisuję prawemu facetowi - czy jesteś tym, który pracuje w Fred H.? –

Powiązane problemy