简要背景:广泛使用的许多(大多数?)当代编程语言至少都具有一些共同的ADT(抽象数据类型),特别是,
字符串(由字符组成的序列)
列表(值的有序集合),以及
基于映射的类型(将键映射到值的无序数组)
在R编程语言中,前两个分别作为character
和实现vector
。
当我开始学习R时,几乎从一开始就显而易见两件事:list
是R中最重要的数据类型(因为它是R的父类data.frame
),第二,我至少不了解它们的工作方式,至少不够好,无法在我的代码中正确使用它们。
一方面,在我看来,R的list
数据类型是对映射ADT的简单实现(dictionary
在Python,NSMutableDictionary
Objective C,hash
Perl和Ruby,object literal
Javascript等中)。
例如,通过将键值对传递给构造函数(在Python中dict
不是list
)来创建它们,就像创建Python字典一样:
x = list("ev1"=10, "ev2"=15, "rv"="Group 1")
然后您就可以像访问Python词典那样访问R列表中的项目,例如x['ev1']
。同样,您可以通过以下方式仅检索“键”或“值”:
names(x) # fetch just the 'keys' of an R list
# [1] "ev1" "ev2" "rv"
unlist(x) # fetch just the 'values' of an R list
# ev1 ev2 rv
# "10" "15" "Group 1"
x = list("a"=6, "b"=9, "c"=3)
sum(unlist(x))
# [1] 18
但是R list
也不同于其他映射类型的ADT(无论如何,从我所学的语言中)。我的猜测是,这是S最初规格的结果,即从头开始设计数据/统计DSL(特定领域语言)的意图。
R list
和其他广泛使用的语言(例如Python,Perl,JavaScript)的映射类型之间的三个重要区别:
首先,list
R中的s是向量的有序集合,即使这些值是键控的(即,键可以是任何可散列的值,而不仅仅是顺序整数)。几乎总是其他语言的映射数据类型是无序的。
第二,list
S可从即使你在一个从来没有通过函数返回list
,当你调用的函数,并且即使返回的功能list
不包含(明确)list
构造函数(当然,你可以解决这个问题在实践中将返回的结果包装到unlist
)中:
x = strsplit(LETTERS[1:10], "") # passing in an object of type 'character'
class(x) # returns 'list', not a vector of length 2
# [1] list
一个第三讨论R的独特功能list
S:它似乎并不认为他们可以是另一种ADT的成员,如果你尝试这样做,那么主容器被裹挟到list
。例如,
x = c(0.5, 0.8, 0.23, list(0.5, 0.2, 0.9), recursive=TRUE)
class(x)
# [1] list
我在这里的意图不是批评语言或其记录方式。同样,我并不是在暗示list
数据结构或其行为有问题。我要做的只是纠正我对它们如何工作的理解,以便可以在我的代码中正确使用它们。
以下是我想更好地理解的一些事情:
有哪些规则确定何时函数调用将返回
list
(例如,strsplit
上面陈述的表达式)?如果我没有明确分配名称
list
(例如list(10,20,30,40)
),默认名称是否只是以1开头的连续整数?(我想,但我不确定答案是否定的,否则我们将无法强制将这种类型的list
向量强制为w或对的调用unlist
。)为什么这两个不同的运算符,
[]
和[[]]
返回相同的结果?x = list(1, 2, 3, 4)
这两个表达式都返回“ 1”:
x[1]
x[[1]]
为什么这两个表达式不能返回相同的结果?
x = list(1, 2, 3, 4)
x2 = list(1:4)
请不要将我指向R文档(),我已经仔细阅读了该文档?list
,R-intro
它不能帮助我回答上面刚刚提到的问题类型。
(最后,我最近了解并开始使用一个R包(在CRAN上可用)hash
,该包通过S4类实现常规的映射类型行为;我当然可以推荐此包。)
list
了R中不像哈希的方式。我还有一个我认为值得注意的地方。 list
R中的R可以具有两个具有相同引用名称的成员。认为这obj <- c(list(a=1),list(a=2))
是有效的,并返回带有两个名为“ a”的值的列表。在这种情况下,对的调用obj["a"]
将仅返回第一个匹配列表元素。使用R中的环境,您可以获得与每个引用名称仅包含一项的哈希类似(也许相同)的行为。例如x <- new.env(); x[["a"]] <- 1; x[["a"]] <- 2; x[["a"]]
x = list(1, 2, 3, 4)
,这两个返回的结果都不相同:x[1]
和x[[1]]
。第一个返回列表,第二个返回数字向量。在下面滚动,对我来说似乎德克是唯一正确回答此问题的人。