【发布时间】:2010-05-18 14:10:48
【问题描述】:
我有一个小问题:我在 R 中找不到字典数据结构,所以我改用列表(如 "word"->number)。
那么,如何获取键列表。
【问题讨论】:
我有一个小问题:我在 R 中找不到字典数据结构,所以我改用列表(如 "word"->number)。
那么,如何获取键列表。
【问题讨论】:
是的,list 类型是一个很好的近似值。您可以使用列表中的names() 来设置和检索“密钥”:
> foo <- vector(mode="list", length=3)
> names(foo) <- c("tic", "tac", "toe")
> foo[[1]] <- 12; foo[[2]] <- 22; foo[[3]] <- 33
> foo
$tic
[1] 12
$tac
[1] 22
$toe
[1] 33
> names(foo)
[1] "tic" "tac" "toe"
>
【讨论】:
environment 类型用于 R 中,但它不太常见/鲜为人知。
如果您的“数字”值都是相同的模式,您甚至不需要列表。如果我以 Dirk Eddelbuettel 为例:
> foo <- c(12, 22, 33)
> names(foo) <- c("tic", "tac", "toe")
> foo
tic tac toe
12 22 33
> names(foo)
[1] "tic" "tac" "toe"
仅当您的值是混合模式(例如字符和数字)或向量时才需要列表。
对于列表和向量,单个元素可以按名称进行子集化:
> foo["tac"]
tac
22
或者列表:
> foo[["tac"]]
[1] 22
【讨论】:
c(12,22,33) 的列表? unlist(lapply(FUN=function(a){foo[[a]]},X = 1:length(foo))) 很不方便。有什么准备好的功能吗?移动问题here
为了扩展 Calimo 的一点点答案,我提供了一些在 R 中创建此准词典时您可能会发现有用的东西:
a) 如何返回字典的所有VALUES:
>as.numeric(foo)
[1] 12 22 33
b) 检查字典是否包含键:
>'tic' %in% names(foo)
[1] TRUE
c) 如何在字典中添加新的键、值对:
c(foo,tic2=44)
结果:
tic tac toe tic2
12 22 33 44
d) 如何满足 REAL DICTIONARY 的要求 - 键不能重复(唯一键)?您需要结合 b) 和 c) 并构建函数来验证是否存在这样的密钥,并执行您想要的操作:例如,如果新的与旧的不同,则不允许插入、更新值,或者以某种方式重建密钥(例如添加一些数字,因此它是唯一的)
e) 如何从字典中按键删除对:
foo
【讨论】:
c(foo, tic2=NULL)。有什么解决办法吗?
首先使用字典的原因是性能。虽然您可以在任务中使用命名向量和列表是正确的,但问题是它们变得非常缓慢并且随着数据的增加而占用大量内存。
然而很多人不知道的是,R 确实有一个内置的字典数据结构:带有hash = TRUE选项的环境
请参阅以下示例以了解如何使其工作:
# vectorize assign, get and exists for convenience
assign_hash <- Vectorize(assign, vectorize.args = c("x", "value"))
get_hash <- Vectorize(get, vectorize.args = "x")
exists_hash <- Vectorize(exists, vectorize.args = "x")
# keys and values
key<- c("tic", "tac", "toe")
value <- c(1, 22, 333)
# initialize hash
hash = new.env(hash = TRUE, parent = emptyenv(), size = 100L)
# assign values to keys
assign_hash(key, value, hash)
## tic tac toe
## 1 22 333
# get values for keys
get_hash(c("toe", "tic"), hash)
## toe tic
## 333 1
# alternatively:
mget(c("toe", "tic"), hash)
## $toe
## [1] 333
##
## $tic
## [1] 1
# show all keys
ls(hash)
## [1] "tac" "tic" "toe"
# show all keys with values
get_hash(ls(hash), hash)
## tac tic toe
## 22 1 333
# remove key-value pairs
rm(list = c("toe", "tic"), envir = hash)
get_hash(ls(hash), hash)
## tac
## 22
# check if keys are in hash
exists_hash(c("tac", "nothere"), hash)
## tac nothere
## TRUE FALSE
# for single keys this is also possible:
# show value for single key
hash[["tac"]]
## [1] 22
# create new key-value pair
hash[["test"]] <- 1234
get_hash(ls(hash), hash)
## tac test
## 22 1234
# update single value
hash[["test"]] <- 54321
get_hash(ls(hash), hash)
## tac test
## 22 54321
编辑:在这个答案的基础上,我写了一篇包含更多上下文的博文:http://blog.ephorie.de/hash-me-if-you-can
【讨论】:
hash 包现已推出: https://cran.r-project.org/web/packages/hash/hash.pdf
示例
h <- hash( keys=letters, values=1:26 )
h <- hash( letters, 1:26 )
h$a
# [1] 1
h$foo <- "bar"
h[ "foo" ]
# <hash> containing 1 key-value pair(s).
# foo : bar
h[[ "foo" ]]
# [1] "bar"
【讨论】:
Dirk 答案的较短变化:
# Create a Color Palette Dictionary
> color <- c('navy.blue', 'gold', 'dark.gray')
> hex <- c('#336A91', '#F3C117', '#7F7F7F')
> # Create List
> color_palette <- as.list(hex)
> # Name List Items
> names(color_palette) <- color
>
> color_palette
$navy.blue
[1] "#336A91"
$gold
[1] "#F3C117"
$dark.gray
[1] "#7F7F7F"
【讨论】:
我只是评论一下,当您尝试“伪造”字典时,您也可以从 table 中获得很多好处,例如
> x <- c("a","a","b","b","b","c")
> (t <- table(x))
x
a b c
2 3 1
> names(t)
[1] "a" "b" "c"
> o <- order(as.numeric(t))
> names(t[o])
[1] "c" "a" "b"
等等
【讨论】:
as.numeric() 是必要的。该表已经是数字的。您可以使用names(t[order(t)]) 获得相同的结果