开发者

Working with dictionaries/lists to get list of keys

I have trivial question: I couldn't find a dictionary data structure in R, so I used list in开发者_如何转开发stead (like "word"->number). So, how do I get the list of keys.


Yes, the list type is a good approximation. You can use names() on your list to set and retrieve the 'keys':

> 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"
> 


You do not even need lists if your "number" values are all of the same mode. If I take Dirk Eddelbuettel's example:

> foo <- c(12, 22, 33)
> names(foo) <- c("tic", "tac", "toe")
> foo
tic tac toe
 12  22  33
> names(foo)
[1] "tic" "tac" "toe"

Lists are only required if your values are either of mixed mode (for example characters and numbers) or vectors.

For both lists and vectors, an individual element can be subsetted by name:

> foo["tac"]
tac 
 22 

Or for a list:

> foo[["tac"]]
[1] 22


The reason for using dictionaries in the first place is performance. Although it is correct that you can use named vectors and lists for the task the issue is that they are becoming quite slow and memory hungry with more data.

Yet what many people don't know is that R has indeed an inbuilt dictionary data structure: environments with the option hash = TRUE

See the following example for how to make it work:

# 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

Edit: On the basis of this answer I wrote a blog post with some more context: http://blog.ephorie.de/hash-me-if-you-can


To extend a little bit answer of Calimo I present few more things you may find useful while creating this quasi dictionaries in R:

a) how to return all the VALUES of the dictionary:

>as.numeric(foo)
[1] 12 22 33

b) check whether dictionary CONTAINS KEY:

>'tic' %in% names(foo)
[1] TRUE

c) how to ADD NEW key, value pair to dictionary:

c(foo,tic2=44)

results:

tic       tac       toe     tic2
12        22        33        44 

d) how to fulfill the requirement of REAL DICTIONARY - that keys CANNOT repeat(UNIQUE KEYS)? You need to combine b) and c) and build function which validates whether there is such key, and do what you want: e.g don't allow insertion, update value if the new differs from the old one, or rebuild somehow key(e.g adds some number to it so it is unique)

e) how to DELETE pair BY KEY from dictionary:

foo<-foo[which(foo!=foo[["tac"]])]


The package hash is now available: https://cran.r-project.org/web/packages/hash/hash.pdf

Examples

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"


Shorter variation of Dirk's answer:

# 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"


I'll just comment you can get a lot of mileage out of table when trying to "fake" a dictionary also, e.g.

> 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"

etc.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜