我发现R person对象的以下行为非常意外:
让我们创建一个多人对象:
a = c(person("Huck", "Finn"), person("Tom", "Sawyer"))
想象一下,我们想要更新对象中一个人的给定名称:
a[[1]]$given <- 'Huckleberry'
然后,如果我们检查我们的对象,我惊讶地发现:
> a
[1] " <> [] ()" "Tom Sawyer"
哈克贝利·芬恩去哪儿了?! (请注意,如果我们只用一个人对象来尝试它,它就可以正常工作。)为什么会发生这种情况?
我们如何才能完成上述工作,以便我们能够更正逻辑地纠正名字?
答案 0 :(得分:3)
您想要的语法是
a <- c(person("Huck", "Finn"), person("Tom", "Sawyer"))
a[1]$given<-"Huckleberry"
a
#[1] "Huckleberry Finn" "Tom Sawyer"
一群人仍然是一个&#34;并且它拥有自己的特殊索引函数[.person
和concat函数c.person
,因此它可能具有与您期望的不同的行为。问题是[[ ]]
弄乱了潜在的隐藏列表。
实际上,它很有趣,因为他们已经重载了person
的几乎所有索引方法,但没有重载[<-
或[[<-
的那些索引方法真的很重要导致错误的是什么因为到这里,我们是相同的
`$<-`(`[`(a,1), "given", "Huckleberry") #works
`$<-`(`[[`(a,1), "given", "Huckleberry") #works
但是当我们到达
时`[<-`(a, 1, `$<-`(`[`(a,1), "given", "Huckleberry")) #works
`[[<-`(a, 1, `$<-`(`[[`(a,1), "given", "Huckleberry")) #no work
我们看到了不同之处。在检索期间发生的特殊包装/展开不会在分配期间发生。
所以,正在发生的事情是一个&#34;人&#34;始终是列表的列表。外部列表包含所有人,内部列表包含数据。你可以想到像这样的数据
x<-list(
list(name="a"),list(name="b")
)
y<-list(
list(name="c")
)
其中x
是两个人的集合,y
是&#34;单个&#34;人。当你这样做
x[1]<-y
x
你最终得到了
list(
list(name="c"),list(name="b")
)
因为您要使用列表替换列表,列表是[
索引与列表一起使用的方式。但是,如果您尝试使用列表列表替换[[1]]
处的元素,则该列表将嵌套。例如
x[[1]]<-y
x
变为
x<-list(
list(list(name="c")),list(name="b")
)
当它在第一个位置打印人时,额外的嵌套水平是令人困惑的R。第一个人在第二级没有任何命名元素,所以当它打印时,它将返回
emptyp <- structure(list(structure(list(), class="person")), class="person")
utils:::format.person(emptyp)
# " <> [] ()"
给出的是它试图放置姓名,电子邮件地址,角色和评论的符号。