如何在R中使用多个相同类型的对象填充插槽?

如何在R中使用多个相同类型的对象填充插槽?,r,class,object,slot,R,Class,Object,Slot,假设我想定义两个类,句子和单词。每个单词对象都有一个字符串和一个词性(pos)。每个句子包含一定数量的单词,并有一个额外的数据槽 Word类很容易定义 wordSlots <- list(word = "character", pos = "character") wordProto <- list(word = "", pos = "") setClass("Word", slots = wordSlots, prototype = wordProto) Word <

假设我想定义两个类,
句子
单词
。每个单词对象都有一个字符串和一个词性(pos)。每个句子包含一定数量的单词,并有一个额外的数据槽

Word
类很容易定义

wordSlots <- list(word = "character", pos = "character")
wordProto <- list(word = "", pos = "")
setClass("Word", slots = wordSlots, prototype = wordProto)    
Word <- function(word, pos) new("Word", word=word, pos=pos)
那么这个句子只能包含一个单词。很明显,我可以用很多槽来定义它,每个字对应一个槽,但长度有限

但是,如果我这样定义
句子
类:

sentenceSlots <- list(words = "list", stats = "numeric")
sentenceProto <- list(words = list(Word()), stats = 0)
setClass("Sentence", slots = sentenceSlots, prototype = sentenceProto)

sentenceSlots我建议只解决这类问题。请记住,R不完全适合面向对象编程风格,并且每个解决方案几乎不显示其他语言如java或C++的坚固性。但是,您可以使用
单词
槽作为列表声明您的
句子
类。然后将构造函数定义为:

   Sentence<-function(words,stats) {
     #check for the components' class of words argument
     if (!is.list(words) || !all(sapply(words,function(x) class(x)=="Word"))) stop("Not valid words argument")
     #create the object
      new("Sentence", words=words, stats=stats)
   }

我不认为最后一步是必要的。不管你做什么,用户总是会把事情搞砸。例如,他可以绕过构造函数直接调用
new
函数。或者他可以将
单词
类设置为任意对象,然后将其传递给
句子
。正如我所说,R不适合这种编程风格,因此您应该经常采用某种非最优解决方案。

记住R在向量上工作得很好,第一步是考虑“单词”而不是“单词”

## constructor, accessors, subset (also need [[, [<-, [[<- methods)
.Words <- setClass("Words",
    representation(words="character", parts="character"))
words <- function(x) x@words
parts <- function(x) x@parts
setMethod("length", "Words", function(x) length(words(x)))
setMethod("[", c("Words", "ANY", "missing"), function(x, i, j, ...) {
    initialize(x, words=words(x)[i], parts=parts(x)[i], ...)
})

## validity
setValidity("Words", function(object) {
    if (length(words(object)) == length(parts(object)))
        NULL
    else
        "'words()' and 'parts()' are not the same length"
})
然后可以编写一个更加用户友好的构造函数,但基本功能是

## 0 Sentences
.Sentences()
## 1 sentence of 0 words
.Sentences(unlistData=.Words(), partitioning=PartitioningByEnd(0))
## 3 sentences of 2, 0, and 3 words
s3 <- .Sentences(unlistData=.Words(words=letters[1:5], parts=LETTERS[1:5]), 
    partitioning=PartitioningByEnd(c(2, 2, 5)))
请注意,一些典型的操作速度很快,因为它们可以在不创建或销毁S4实例的情况下对“未列出”元素进行操作,例如,强制将所有“单词”大写

setMethod(toupper, "Words", function(x) { x@word <- toupper(x@word); x })
setMethod(toupper, "Sentences", function(x) relist(toupper(unlist(x)), x))

setMethod(toupper,“Words”,函数(x){x@word我认为我之前的建议(我删除了)很好。在句子中,将其改为单词向量,而不是单词列表。我在R中没有做太多OO编程,但我认为这应该有效。它不会将其解释为向量,而是列表。With
words=“vector”
x可以理解,对吗?因为您有两个Word类型的元素和一个numeric类型的元素?在设置之前,它将被强制执行。这3个元素是否对应于句子对象中的stats?在我看来,您可能希望通过x@wordsA解决方法可能是检查clas您的
语句
构造函数中列表组件的。请参见
sp
包的
多边形
构造函数作为示例。然后您可以重新定义
@做了我需要做的所有事情,而且比我预期的要容易。非常清晰且信息丰富。为我提供了很多解决问题的方法问题
library(IRanges)
.Sentences = setClass("Sentences",
    contains="CompressedList",    
    prototype=c(elementType="Words"))
## 0 Sentences
.Sentences()
## 1 sentence of 0 words
.Sentences(unlistData=.Words(), partitioning=PartitioningByEnd(0))
## 3 sentences of 2, 0, and 3 words
s3 <- .Sentences(unlistData=.Words(words=letters[1:5], parts=LETTERS[1:5]), 
    partitioning=PartitioningByEnd(c(2, 2, 5)))
> s3[[1]]
An object of class "Words"
Slot "word":
[1] "a" "b"

Slot "part":
[1] "A" "B"

> s3[[2]]
An object of class "Words"
Slot "word":
character(0)

Slot "part":
character(0)

> s3[[3]]
An object of class "Words"
Slot "word":
[1] "c" "d" "e"

Slot "part":
[1] "C" "D" "E"
setMethod(toupper, "Words", function(x) { x@word <- toupper(x@word); x })
setMethod(toupper, "Sentences", function(x) relist(toupper(unlist(x)), x))