数组

数组 属于 R

1 个练习

关于 数组

R 中的list是有序的元素集合,它和vectors在几个方面有所不同:

  • 元素可以是不同的类型(例如把numeric和character混在一起)。
  • 元素可以是复杂的结构(例如向量、其他列表等)。
  • 访问元素时有一些不同的语法。

把它类比成其他语言里的东西并不准确。 R 的list与 Python 字典有些相似,不过list是有序的,可以通过数字下标来访问。 它也与 C 的struct有些相似,区别在于list可以在运行时轻松扩展。

创建列表

给元素起名称(通常叫做“标签”),这种做法在列表中比在向量中更常见:

list(x = 5.3, y = 4.2, color = "blue")
#> $x
#> [1] 5.3

#> $y
#> [1] 4.2

#> $color
#> [1] "blue"

不过标签是可选的,这时 R 会直接使用编号下标:

list(5.3, 4.2, "blue")
#> [[1]]
#> [1] 5.3

#> [[2]]
#> [1] 4.2

#> [[3]]
#> [1] "blue"

访问列表元素

有三种方法可以做到这一点,每种方法适用于不同的场景。

1. 用$tag表示法

如果标签名事先已知,这种方式很常用。

point <- list(x = 5.3, y = 4.2, color = "blue")
#> point$x
#> [1] 5.3
#> point$color
#> [1] "blue"

2. 用[[tag]]表示法

它的好处是标签名可以在运行时才决定。 注意这里用了双层方括号。

want <- "y"
point[[want]] # same as point$y
#> [1] 4.2

3. 用位置下标

无论列表有没有标签,这种方式都适用。 同样,方括号要写两层。

point[[3]] # same as point$color
#> [1] "blue"

添加和删除元素

很简单:给某个元素赋值,如果它已存在就会修改它,如果它是新的就会插入它。

point$color <- "red"
point$trust <- TRUE

# str() gives more compact output than the default display
str(point) 
#> List of 4
#>  $ x    : num 5.3
#>  $ y    : num 4.2
#>  $ color: chr "red"
#>  $ trust: logi TRUE

要删除元素,就给不想要的元素赋值NULL。

point$trust <- NULL
str(point)  
#> List of 3
#>  $ x    : num 5.3
#>  $ y    : num 4.2
#>  $ color: chr "red"

列表是“递归向量”

vector类在技术上被称为atomic vector,因为它只能存放原子值:numeric、character、boolean等等。 由于list可以包含其他列表,它也被称为recursive vector。

这既是一个术语命名上的技术要点,也提醒我们列表可以具有任意复杂的结构。 访问列表元素时,程序员有责任弄清楚会得到什么。

关于列表下标的更多内容

上面的一些例子用双层方括号[[ ]]来访问列表元素。 它会尝试把元素展平为其底层类型,如果你只想要一个数字或字符串,这会很有用。

使用单层方括号[ ]则不会做这种展平,返回的值会是一个子列表。

point[["color"]]
#> [1] "red"  # flattened

point["color"]
#> $color
#> [1] "red"  # sublist

即使子列表不是 R 新手通常想要的东西,也请留意这一点。 为了最大程度的灵活性,许多标准 R 函数会返回list,即使它像这里一样只包含一个原子值。

要把它转换成一个向量,有两种办法。

  1. 用[[1]]取出第一个元素
  2. 使用unlist()函数。
pt <-point["color"]

pt[[1]]
#> [1] "red" # simple 1-element vector

unlist(pt)
#> color 
#> "red"  # 1-element vector with name

使用unlist()时要小心。 在这个简单的例子里,展平结构很有用,但当列表元素更复杂时,它可能会带来意想不到的结果。

Advanced

内部表示

list和原子vector一样,是连续存储的。区别在于,数值向量和布尔向量存储的是值,而列表存储的是指向内存中其他位置对象的引用。

了解这一点对 R 使用者来说并不太重要,但在像 Exercism 这样的多语言社区里,它可能对熟悉其他语言的程序员有帮助。

通过 GitHub 编辑 该链接会在新窗口或标签页中打开

学习 数组