如何在R中将插槽的默认值设置为NULL?

Der*_*ang 11 r s4

我是R.的新手

我正在尝试定义一个类似于树节点的类,也就是说,它有一个左节点和右节点,它应该与父节点属于同一个类.所以我将类定义如下:

setClass('Node', representation=(left='Node',right='Node', ...))
Run Code Online (Sandbox Code Playgroud)

我想通过设置原型将Node的默认值设置为NULL,但R表示如下:

  invalid class "Node" object: invalid object for slot "left" in class "bicluster": got class "NULL", should be or extend class "Node"
Run Code Online (Sandbox Code Playgroud)

但是如果我没有将默认值speficy为NULL,那么默认值将是深度为4的递归节点,我认为这是浪费资源.

我的考虑是不必要的还是有更好的方法来做到这一点?

42-*_*42- 9

有时您需要使用setClassUnion("listOrNULL",members=c("list", "NULL"))NULL来获取定义为列表的槽.我认为现在是一个可用的课程.您的设置不完整时无法测试,但定义超类"NodeOrNull"可能会让您超越初始屏障.


Mar*_*gan 7

这是修改后的答案.

类联合很时髦 - 它们有效地将类插入到现有层次结构的中间,所以list现在突然扩展的内容会延伸listOrNULL.

相反,我会创建一个小的类层次结构,代表一个"树",可以是"空"或"内部"."Internal"类将有一个包含数据(类型为"ANY")的插槽,以及左侧和右侧链接,它们将是"Tree"元素.

setClass("Tree")

setClass("Empty", contains="Tree")

setClass("Internal", contains="Tree",
         representation=representation(elem="ANY", left="Tree", right="Tree"),
         prototype=prototype(left=new("Empty"), right=new("Empty")))
Run Code Online (Sandbox Code Playgroud)

我将为我的Tree编写一个构造函数,其中包含用于创建空树的方法,以及来自元素的树以及左右后代.

setGeneric("Tree", function(elem, left, right) standardGeneric("Tree"),
           signature="elem")

setMethod(Tree, "missing", function(elem, left, right) new("Empty"))

setMethod(Tree, "ANY", function(elem, left, right) {
    new("Internal", elem=elem, left=left, right=right)
})
Run Code Online (Sandbox Code Playgroud)

基本操作是将元素x插入树中t

setGeneric("insert", function(x, t) standardGeneric("insert"))

setMethod(insert, c("ANY", "Empty"), function(x, t) {
    Tree(x, Tree(), Tree())
})

setMethod(insert, c("ANY", "Internal"), function(x, t) {
    if (x < t@elem) {
        l <- insert(x, t@left)
        r <- t@right
    } else {
        l <- t@left
        r <- insert(x, t@right)
    }
    Tree(t@elem, l, r)
})
Run Code Online (Sandbox Code Playgroud)

另一项操作是测试会员资格

setGeneric("member", function(x, t) standardGeneric("member"))

setMethod(member, c("ANY", "Empty"), function(x, t) FALSE)

setMethod(member, c("ANY", "Internal"), function(x, t) {
    if (x < t@elem) member(x, t@left)
    else if (t@elem < x) member(x, t@right)
    else TRUE
})
Run Code Online (Sandbox Code Playgroud)

这个实现的一个有趣的,功能性的属性是它是持久的

> t <- Tree()
> t1 <- insert(10, t)
> t2 <- insert(5, t1)
> t3 <- insert(7, t2)
> t4 <- insert(15, t3)
> which(sapply(1:20, member, t4))
[1]  5  7 10 15
> which(sapply(1:20, member, t2))
[1]  5 10
Run Code Online (Sandbox Code Playgroud)

当存在大量更新时,这不会有效,因为S4类创建效率低,并且因为修改树(例如,添加节点)会将路径中的所有节点复制到新节点.一种不同的方法将树表示matrix为左,右,值三元组.S4实现仍然会有糟糕的性能,因为实例的更新会创建新实例,重复所有内容.所以我最终会进入一个引用类,其中包含字段'value'(树的任意向量matrix和左右关系的向量).