【发布时间】:2011-01-04 06:43:57
【问题描述】:
背景简介:许多(大多数?)广泛使用的当代编程语言至少有少数共同的 ADT [抽象数据类型],特别是,
字符串(由字符组成的序列)
list(值的有序集合),以及
基于映射的类型(将键映射到值的无序数组)
在 R 编程语言中,前两个分别实现为 character 和 vector。
当我开始学习 R 时,有两件事几乎从一开始就很明显:list 是 R 中最重要的数据类型(因为它是 R 的父类data.frame),第二,我不能'不了解它们是如何工作的,至少还不足以在我的代码中正确使用它们。
一方面,在我看来,R 的 list 数据类型是映射 ADT 的简单实现(Python 中的 dictionary,Objective C 中的 NSMutableDictionary,Perl 和 Ruby 中的 hash,@987654332 @ 在 JavaScript 中,等等)。
例如,您可以像创建 Python 字典一样创建它们,通过将键值对传递给构造函数(在 Python 中是 dict 而不是 list):
x = list("ev1"=10, "ev2"=15, "rv"="Group 1")
您可以像访问 Python 字典一样访问 R 列表中的项目,例如,x['ev1']。同样,您可以通过以下方式仅检索 'keys' 或仅检索 'values':
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 lists 也 不同于 其他地图类型 ADT(无论如何都是我学过的语言之一)。我的猜测是,这是 S 初始规范的结果,即从头开始设计数据/统计 DSL [领域特定语言] 的意图。
三个 R lists 与其他广泛使用的语言(例如,Python、Perl、JavaScript)中的映射类型之间的显着差异:
first, R 中的lists 是一个有序 集合,就像向量一样,即使值是键控的(即键可以是任何可散列的值)不仅仅是顺序整数)。几乎总是,其他语言中的映射数据类型是无序的。
second,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 开头的连续整数? (我假设,但我不能确定答案是否定的,否则我们将无法通过调用unlist将这种类型的list强制转换为向量。) -
为什么
[]和[[]]这两个不同的运算符返回相同的结果?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)--我已仔细阅读过它并不能帮助我回答我刚才提到的问题类型。
(最后,我最近了解到并开始使用一个名为 hash 的 R 包(可在 CRAN 上获得),它通过 S4 类实现 传统 地图类型的行为;我当然可以推荐这个包.)
【问题讨论】:
-
使用
x = list(1, 2, 3, 4),这两个都不会返回相同的结果:x[1]和x[[1]]。第一个返回一个列表,第二个返回一个数值向量。在我看来,Dirk 是唯一正确回答这个问题的受访者。 -
我没有注意到有人在您的列表中扩展 R 中的
list不像哈希。我还有一个我认为值得注意的。 R 中的list可以有两个具有相同引用名称的成员。考虑obj <- c(list(a=1),list(a=2))是有效的并返回一个包含两个命名值“a”的列表。在这种情况下,调用obj["a"]将只返回第一个匹配的列表元素。您可以使用 R 中的环境获得与哈希类似(可能相同)的行为,每个引用名称只有一个项目。x <- new.env(); x[["a"]] <- 1; x[["a"]] <- 2; x[["a"]] -
在过去的 6 个月里,我已将这篇帖子连同答案重新阅读了 3 次,每次都获得了更多的启发。很好的问题和一些很好的答案。谢谢。
标签: r list data-structures language-features abstract-data-type