Mam trywialne pytanie: nie mogłem znaleźć struktury danych słownika w R, więc zamiast tego użyłem listy (np. „Słowo” -> liczba). W tej chwili mam problem ze znalezieniem listy kluczy. Czy ktoś wie?
Odpowiedzi:
Tak, list
typ jest dobrym przybliżeniem. Możesz użyć names()
na swojej liście, aby ustawić i pobrać `` klucze '':
> 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
typ jest używany do tego w R, ale jest mniej powszechny / mniej znany.
Nie potrzebujesz nawet list, jeśli wszystkie wartości „liczb” są w tym samym trybie. Jeśli wezmę przykład Dirka Eddelbuettela:
> foo <- c(12, 22, 33)
> names(foo) <- c("tic", "tac", "toe")
> foo
tic tac toe
12 22 33
> names(foo)
[1] "tic" "tac" "toe"
Listy są wymagane tylko wtedy, gdy wartości są albo w trybie mieszanym (na przykład znaki i cyfry), albo w wektorach.
Zarówno w przypadku list, jak i wektorów, pojedynczy element można podzielić według nazwy:
> foo["tac"]
tac
22
Lub listę:
> foo[["tac"]]
[1] 22
Aby nieco rozszerzyć odpowiedź Calimo, przedstawiam jeszcze kilka rzeczy, które mogą się przydać podczas tworzenia tych quasi słowników w R:
a) jak zwrócić wszystkie WARTOŚCI słownika:
>as.numeric(foo)
[1] 12 22 33
b) sprawdź, czy słownik ZAWIERA KLUCZ:
>'tic' %in% names(foo)
[1] TRUE
c) jak DODAĆ NOWY klucz, parę wartości do słownika:
c (foo, tic2 = 44)
wyniki:
tic tac toe tic2
12 22 33 44
d) jak spełnić wymóg PRAWDZIWEGO SŁOWNIKA - aby klucze NIE MOGły się powtarzać (UNIKALNE KLUCZE)? Musisz połączyć b) ic) i zbudować funkcję, która sprawdza, czy istnieje taki klucz i robić co chcesz: np. Nie zezwalaj na wstawianie, aktualizuj wartość, jeśli nowy różni się od starego, lub przebudowuj jakoś klucz (np. dodaje do niego pewną liczbę, więc jest unikalna)
e) jak USUNĄĆ parę WEDŁUG KLUCZA ze słownika:
foo <-foo [które (foo! = foo [["tac"]])]
c(foo, tic2=NULL)
. Jakieś obejście?
Powodem używania słowników w pierwszej kolejności jest wydajność. Chociaż prawdą jest, że możesz używać nazwanych wektorów i list do zadania, problem polega na tym, że stają się one dość powolne i wymagają większej ilości pamięci z większą ilością danych.
Jednak wielu ludzi nie wie, że R ma rzeczywiście wbudowaną strukturę danych słownikowych: środowiska z opcjąhash = TRUE
Zobacz poniższy przykład, jak to działa:
# 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
Edycja : Na podstawie tej odpowiedzi napisałem post na blogu z większym kontekstem: http://blog.ephorie.de/hash-me-if-you-can
Skrót pakietu jest już dostępny: https://cran.r-project.org/web/packages/hash/hash.pdf
Przykłady
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"
Krótsza odmiana odpowiedzi Dirka:
# 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"
Tylko skomentuję, że table
próbując „sfałszować” słownik również można uzyskać dużo kilometrów , np
> 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"
itp.
as.numeric()
jest to konieczne. Tabela jest już numeryczna. Możesz uzyskać ten sam wynik dziękinames(t[order(t)])