R Language
HashMaps
खोज…
हैश नक्शे के रूप में वातावरण
ध्यान दें: बाद के मार्ग में, शब्द हैश मैप और हैश टेबल को परस्पर उपयोग किया जाता है और एक ही अवधारणा को संदर्भित करता है, अर्थात्, एक आंतरिक हैश फ़ंक्शन के उपयोग के माध्यम से कुशल कुंजी लुकअप प्रदान करने वाला डेटा संरचना।
परिचय
यद्यपि R एक देशी हैश टेबल संरचना प्रदान नहीं करता है, इसी तरह की कार्यक्षमता इस तथ्य का लाभ उठाकर प्राप्त की जा सकती है कि environment
ऑब्जेक्ट new.env
(डिफ़ॉल्ट रूप से) से लौटा new.env
कुंजी लुकअप प्रदान करता है। निम्नलिखित दो कथन समतुल्य हैं, क्योंकि hash
पैरामीटर TRUE
चूक करता है:
H <- new.env(hash = TRUE)
H <- new.env()
इसके अतिरिक्त, कोई निर्दिष्ट कर सकता है कि आंतरिक हैश तालिका size
पैरामीटर के माध्यम से एक विशेष आकार के साथ पूर्व-आबंटित है, जिसका डिफ़ॉल्ट मान 29 है। अन्य सभी R वस्तुओं की तरह, environment
अपनी स्मृति का प्रबंधन करता है और आवश्यकतानुसार क्षमता में वृद्धि करेगा। , इसलिए जब size
लिए एक गैर-डिफ़ॉल्ट मूल्य का अनुरोध करना आवश्यक नहीं है, तो ऐसा करने में थोड़ा सा प्रदर्शन लाभ हो सकता है यदि ऑब्जेक्ट (अंततः) में बहुत बड़ी संख्या में तत्व होंगे। यह ध्यान देने योग्य है कि size
माध्यम से अतिरिक्त स्थान आवंटित करना, अपने आप में, बड़े स्मृति पदचिह्न के साथ किसी वस्तु में परिणाम नहीं करता है:
object.size(new.env())
# 56 bytes
object.size(new.env(size = 10e4))
# 56 bytes
निवेशन
तत्वों की प्रविष्टि [[<-
या $<-
environment
वर्ग के लिए प्रदान की गई विधियों का उपयोग करके की जा सकती है, लेकिन "एकल ब्रैकेट" असाइनमेंट ( [<-
) का उपयोग करके नहीं :
H <- new.env()
H[["key"]] <- rnorm(1)
key2 <- "xyz"
H[[key2]] <- data.frame(x = 1:3, y = letters[1:3])
H$another_key <- matrix(rbinom(9, 1, 0.5) > 0, nrow = 3)
H["error"] <- 42
#Error in H["error"] <- 42 :
# object of type 'environment' is not subsettable
R के अन्य पहलुओं की तरह, पहला तरीका ( object[[key]] <- value
) आम तौर पर दूसरे के लिए पसंद किया जाता है ( object$key <- value
) क्योंकि पूर्व मामले में, एक वैरिएबल का उपयोग शाब्दिक मान के बजाय शायद किया जा सकता है। (उदाहरण के लिए key2
ऊपर के उदाहरण में)।
जैसा कि आम तौर पर हैश मैप कार्यान्वयन के साथ होता है, environment
ऑब्जेक्ट डुप्लिकेट कुंजियों को संग्रहीत नहीं करेगा। मौजूदा कुंजी के लिए की-वैल्यू पेयर सम्मिलित करने का प्रयास पहले संग्रहीत मान को बदल देगा:
H[["key3"]] <- "original value"
H[["key3"]] <- "new value"
H[["key3"]]
#[1] "new value"
मुख्य लुकअप
इसी तरह, तत्वों को [[
या $
साथ एक्सेस किया जा सकता है, लेकिन [
:]
H[["key"]]
#[1] 1.630631
H[[key2]] ## assuming key2 <- "xyz"
# x y
# 1 1 a
# 2 2 b
# 3 3 c
H$another_key
# [,1] [,2] [,3]
# [1,] TRUE TRUE TRUE
# [2,] FALSE FALSE FALSE
# [3,] TRUE TRUE TRUE
H[1]
#Error in H[1] : object of type 'environment' is not subsettable
हैश मैप का निरीक्षण
साधारण environment
होने के नाते, हैश मैप का निरीक्षण विशिष्ट तरीकों से किया जा सकता है:
names(H)
#[1] "another_key" "xyz" "key" "key3"
ls(H)
#[1] "another_key" "key" "key3" "xyz"
str(H)
#<environment: 0x7828228>
ls.str(H)
# another_key : logi [1:3, 1:3] TRUE FALSE TRUE TRUE FALSE TRUE ...
# key : num 1.63
# key3 : chr "new value"
# xyz : 'data.frame': 3 obs. of 2 variables:
# $ x: int 1 2 3
# $ y: chr "a" "b" "c"
rm
का उपयोग करके तत्वों को हटाया जा सकता है:
rm(list = c("key", "key3"), envir = H)
ls.str(H)
# another_key : logi [1:3, 1:3] TRUE FALSE TRUE TRUE FALSE TRUE ...
# xyz : 'data.frame': 3 obs. of 2 variables:
# $ x: int 1 2 3
# $ y: chr "a" "b" "c"
लचीलापन
हैश टेबल के रूप में environment
वस्तुओं का उपयोग करने के प्रमुख लाभों में से एक उनके मूल्य को किसी भी प्रकार की वस्तु के रूप में संग्रहीत करने की उनकी क्षमता है, यहां तक कि अन्य environment
भी हैं :
H2 <- new.env()
H2[["a"]] <- LETTERS
H2[["b"]] <- as.list(x = 1:5, y = matrix(rnorm(10), 2))
H2[["c"]] <- head(mtcars, 3)
H2[["d"]] <- Sys.Date()
H2[["e"]] <- Sys.time()
H2[["f"]] <- (function() {
H3 <- new.env()
for (i in seq_along(names(H2))) {
H3[[names(H2)[i]]] <- H2[[names(H2)[i]]]
}
H3
})()
ls.str(H2)
# a : chr [1:26] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" ...
# b : List of 5
# $ : int 1
# $ : int 2
# $ : int 3
# $ : int 4
# $ : int 5
# c : 'data.frame': 3 obs. of 11 variables:
# $ mpg : num 21 21 22.8
# $ cyl : num 6 6 4
# $ disp: num 160 160 108
# $ hp : num 110 110 93
# $ drat: num 3.9 3.9 3.85
# $ wt : num 2.62 2.88 2.32
# $ qsec: num 16.5 17 18.6
# $ vs : num 0 0 1
# $ am : num 1 1 1
# $ gear: num 4 4 4
# $ carb: num 4 4 1
# d : Date[1:1], format: "2016-08-03"
# e : POSIXct[1:1], format: "2016-08-03 19:25:14"
# f : <environment: 0x91a7cb8>
ls.str(H2$f)
# a : chr [1:26] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" ...
# b : List of 5
# $ : int 1
# $ : int 2
# $ : int 3
# $ : int 4
# $ : int 5
# c : 'data.frame': 3 obs. of 11 variables:
# $ mpg : num 21 21 22.8
# $ cyl : num 6 6 4
# $ disp: num 160 160 108
# $ hp : num 110 110 93
# $ drat: num 3.9 3.9 3.85
# $ wt : num 2.62 2.88 2.32
# $ qsec: num 16.5 17 18.6
# $ vs : num 0 0 1
# $ am : num 1 1 1
# $ gear: num 4 4 4
# $ carb: num 4 4 1
# d : Date[1:1], format: "2016-08-03"
# e : POSIXct[1:1], format: "2016-08-03 19:25:14"
सीमाएं
हैश मैप के रूप में environment
वस्तुओं का उपयोग करने की एक प्रमुख सीमा यह है कि आर के कई पहलुओं के विपरीत, तत्व की तलाश / सम्मिलन के लिए वैश्वीकरण का समर्थन नहीं किया जाता है:
names(H2)
#[1] "a" "b" "c" "d" "e" "f"
H2[[c("a", "b")]]
#Error in H2[[c("a", "b")]] :
# wrong arguments for subsetting an environment
Keys <- c("a", "b")
H2[[Keys]]
#Error in H2[[Keys]] : wrong arguments for subsetting an environment
ऑब्जेक्ट में संग्रहीत डेटा की प्रकृति के आधार पर, एक ही बार में कई तत्वों को असाइन करने के लिए vapply
या list2env
का उपयोग करना संभव हो सकता है:
E1 <- new.env()
invisible({
vapply(letters, function(x) {
E1[[x]] <- rnorm(1)
logical(0)
}, FUN.VALUE = logical(0))
})
all.equal(sort(names(E1)), letters)
#[1] TRUE
Keys <- letters
E2 <- list2env(
setNames(
as.list(rnorm(26)),
nm = Keys),
envir = NULL,
hash = TRUE
)
all.equal(sort(names(E2)), letters)
#[1] TRUE
उपरोक्त में से कोई भी विशेष रूप से संक्षिप्त नहीं है, लेकिन लूप आदि के for
उपयोग करना बेहतर हो सकता है, जब की-वैल्यू जोड़े की संख्या बड़ी हो।
पैकेज: हैश
हैश पैकेज आर। में एक हैश संरचना प्रदान करता है। हालांकि, यह आवेषण के लिए समय की शर्तों और इसे एक हैश के रूप में पर्यावरण का उपयोग करने के लिए प्रतिकूल तुलना करता है। यह प्रलेखन बस अपने अस्तित्व को स्वीकार करता है और उपर्युक्त कारणों के लिए नीचे नमूना समय कोड प्रदान करता है। कोई पहचाना हुआ मामला नहीं है जहाँ आज आर कोड में हैश एक उपयुक्त समाधान है।
विचार करें:
# Generic unique string generator
unique_strings <- function(n){
string_i <- 1
string_len <- 1
ans <- character(n)
chars <- c(letters,LETTERS)
new_strings <- function(len,pfx){
for(i in 1:length(chars)){
if (len == 1){
ans[string_i] <<- paste(pfx,chars[i],sep='')
string_i <<- string_i + 1
} else {
new_strings(len-1,pfx=paste(pfx,chars[i],sep=''))
}
if (string_i > n) return ()
}
}
while(string_i <= n){
new_strings(string_len,'')
string_len <- string_len + 1
}
sample(ans)
}
# Generate timings using an enviornment
timingsEnv <- plyr::adply(2^(10:15),.mar=1,.fun=function(i){
strings <- unique_strings(i)
ht1 <- new.env(hash=TRUE)
lapply(strings, function(s){ ht1[[s]] <<- 0L})
data.frame(
size=c(i,i),
seconds=c(
system.time(for (j in 1:i) ht1[[strings[j]]]==0L)[3]),
type = c('1_hashedEnv')
)
})
timingsHash <- plyr::adply(2^(10:15),.mar=1,.fun=function(i){
strings <- unique_strings(i)
ht <- hash::hash()
lapply(strings, function(s) ht[[s]] <<- 0L)
data.frame(
size=c(i,i),
seconds=c(
system.time(for (j in 1:i) ht[[strings[j]]]==0L)[3]),
type = c('3_stringHash')
)
})
पैकेज: listenv
हालांकि package:listenv
पर्यावरण के लिए सूची-जैसा इंटरफ़ेस लागू करता है, हैश जैसे उद्देश्यों के लिए वातावरण के सापेक्ष इसका प्रदर्शन हैश पुनर्प्राप्ति पर खराब है । हालाँकि, यदि इंडेक्स संख्यात्मक हैं, तो यह रिट्रीवल पर काफी तेज़ हो सकता है। हालांकि, उनके पास अन्य फायदे हैं, उदाहरण के लिए package:future
के साथ संगतता package:future
। उस उद्देश्य के लिए इस पैकेज को कवर करना वर्तमान विषय के दायरे से परे है। हालांकि, यहां दिए गए समय कोड का उपयोग पैकेज के लिए उदाहरण के साथ संयोजन में किया जा सकता है: लेखन समय के लिए हैश।
timingsListEnv <- plyr::adply(2^(10:15),.mar=1,.fun=function(i){
strings <- unique_strings(i)
le <- listenv::listenv()
lapply(strings, function(s) le[[s]] <<- 0L)
data.frame(
size=c(i,i),
seconds=c(
system.time(for (k in 1:i) le[[k]]==0L)[3]),
type = c('2_numericListEnv')
)
})