简要背景:广泛使用的许多(大多数?)当代编程语言至少都具有一些共同的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)的映射类型之间的三个重要区别:
首先,listR中的s是向量一样的有序集合,即使值是有键的(即,键可以是任何可散列的值,而不仅是连续的整数)。几乎总是其他语言的映射数据类型是无序的。
第二,listS可从即使你在一个从来没有通过函数返回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的独特功能listS:它似乎并不认为他们可以是另一种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类实现常规的映射类型行为;我当然可以推荐此包。)
慕田峪7331174
湖上湖