R:在对象列表上使用toString

时间:2014-09-05 01:35:48

标签: r

问题

如何使toString以与toString输出单个对象相同的方式输出列表中的每个元素?

解释

我创建了一个类,为它实现了to.character方法。当我在一个对象上使用as.charactertoString时,它可以正常工作。但是如果我在对象列表中使用这些函数,我会得到一个无法提供信息的字符串,这似乎是deparse的输出。

示例代码:

setClass("my.class",
    slots = c(value = "character"))

my.class <- function(value) {
  new("my.class", value = value)
}

setMethod("as.character", "my.class", function (x) {
  return(paste0('MyClass(',x@value,')'))
})

obj1 = my.class("val1")
obj2 = my.class("val2")

# desired: MyClass(val1)
# actual:  MyClass(val1)
message(toString(obj1))

# desired: MyClass(val1)
# actual:  <S4 object of class "my.class">
message(toString(list(obj1)))

# desired: MyClass(val1), MyClass(val2)
# actual:  <S4 object of class "my.class">, <S4 object of class "my.class">
message(toString(list(obj1, obj2)))

# FYI:
# outputs: <S4 object of class structure("my.class", package = ".GlobalEnv")>
message(deparse(obj1))

1 个答案:

答案 0 :(得分:2)

嗯,toString基本上是paste()的包装器。问题是paste(list(obj1, obj2))paste(obj1, obj2)相比的运行方式。当您传递这样的列表时,内部paste()代码会运行一个名为coerceVector的函数,该函数最终会在每个元素上调用类似deparse的函数。 S3类

会发生类似的事情
paste(list(lm(1:10~rnorm(10)), lm(1:10~rnorm(10))))

如果您定义了自己的集合类怎么办?例如

setClass("my.classes",
    slots = c(values = "list"))

setMethod("as.character", "my.classes", function (x) {
  sapply(x@values, function(z) as(z, "character"))
})

my.classes <- function(...) {
  new("my.classes", values = list(...))
}

list1 <- my.classes(obj1, obj2)
toString(list1)
# [1] "MyClass(val1), MyClass(val2)"

或许你可以为列表创建一个特殊的toString方法?这看起来像

toString.list <- function(x, ...) {
    paste(sapply(x, toString), collapse=", ")
}
然后你会打电话给

toString(list(obj1, obj2))
# [1] "MyClass(val1), MyClass(val2)"

问题是,如果任何函数依赖于toString.default的列表对象的默认行为,那么它似乎不那么安全,但肯定更容易。

让我澄清一下,我不是S4级专家,但在查看C代码之后,我真的无法找到解决paste()问题的方法。