2013-02-10 11 views
12

Ich habe etwas Erfahrung mit S4 Objekte und ihre Steckplätze, so dass ich weiß, wie auf bestimmte Steckplätze und Sub-Steckplätze zugreifen. Was ich gerne lernen würde, ist, wie man ein Objekt in der Weise "entschlitzt", wie unlist eine S3 Liste auseinander nimmt.
Mein unmittelbares Ziel ist es, ein S4 Gegenstück zu einem meiner Spielzeug zu haben, die die Anzahl der Elemente eines Objekts zurückgibt:Gibt es ein S4, das unlist() entspricht?

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

(ohne Messe in meinem Code :-) lacht). Ich hoffe, dass ich keine Rekursionsroutine schreiben muss, die Slots nacheinander extrahiert, um sie zu konvertieren.

Edit: Ich weiß object.size wird den Bytecount zurückgeben; Nicht, was ich hier will.

+1

Sie vielleicht einen Blick auf 'str()' ('utils ::: str haben wollen .default 'wirklich) - beide Ergebnisse, wenn sie auf S4-Objekte angewendet werden, und der Code, der verwendet wird, um durch alle Slots eines S4-Objekts zu gehen. –

Antwort

9

(Dies wird überarbeitet, um näher an einer vorherigen, gelöschten Antwort zu sein, mit slotName und slot anstatt sich auf attributes zu verlassen). Wir könnten eine Funktion schreiben, die prüfen, ob eine Instanz ein S4-Objekt ist, und wenn ja, extrahiert alle Schlitze als Liste und recurses

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

und dann

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

bei einer einfachen alten Liste zu gelangen die wir für beliebige Zwecke verwenden könnten.

$a 
$a$x 
numeric(0) 

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


$b 
numeric(0) 

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

f Möglicherweise müssen verbessert werden, beispielsweise NULL-Werte oder S4 Klassen von S3 Klassen über setOldClass gemacht zu handhaben. Der Code zu validObject würde meine Wahl von Orten sein, um nach einer umfassenderen Durchquerung zu suchen.

Eine Verallgemeinerung könnte einen Besucher machen, nach dem Vorbild der

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

zB

visitLeavesWith(B(), length) 
+0

Das sieht gut aus - eine gute Verbesserung der (entfernten) anderen Antwort. Ja, ich sollte wahrscheinlich in die Berichtsgrößen von Objekten in Bytes "konvertieren" anstatt in Elementzahlen :-) –

+0

Ich kann dich nur einmal upvote :-). Vielen Dank, dass Sie sich die Zeit genommen haben, Ihren Code zu entschlüsseln. Ich gebe dir volle Anerkennung, wenn ich (wenn) ein Paket von Hilfswerkzeugen baue, die 'lssize' enthalten. –

+0

BTW, also kreditiere ich den richtigen Kerl - bist du der Kerl, der bei Fred H. arbeitet? –

Verwandte Themen