Background
I am working on a parser. I have elements in an INI-like file ...
[USER][mshaffer]
; ; http://randomkeygen.com/
salt.key ^= EE8553FD3B5FD6EE ; 152-bit WEP
salt[^salt.key][key] = salt.key
salt[^salt.key][256] = 4B8186C7668947AA396937AE9C245 ; 256-bit WEB
salt[^salt.key][knox] = "yo;*@];9u0>|>HpZS$F62hL6{lNJ@i" ; Fort Knox
Need
I have a list:
res = list();
I have a string str
that shows the level I want to assign to the list
## [USER][mshaffer] ... salt[^salt.key][knox]
str = "USER|mshaffer|salt|salt.key|knox"
val = "yo;*@];9u0>|>HpZS$F62hL6{lNJ@i"
I would like a function that passing in the str
,val
, res
and return the res
of the list appropriately assigned.
assignValue = function(str, val, res)
{
# // do something here
# verify that the res level is set, if not set to "list()"
# at the appropriate level, assign the val to the res list
res;
}
I would prefer to not use eval(parse(text=x))
if possible. I see that solution. I also have hardcoded a 10-level solution in a for loop. I am looking for a base-R
solution.
Obviously, if I try and do the following via hardcoding:
res[["USER"]][["mshaffer"]][["salt"]][["salt.key"]][["knox"]] = "yo;*@];9u0>|>HpZS$F62hL6{lNJ@i";
it creates the nest I would like:
$USER
$USER$mshaffer
$USER$mshaffer$salt
$USER$mshaffer$salt$salt.key
$USER$mshaffer$salt$salt.key$knox
[1] "yo;*@];9u0>|>HpZS$F62hL6{lNJ@i"
Question: How to create a function that assigns a value to a deeply nested list based on a string indicator of the nest depth?
CodePudding user response:
Here is a simple recursive function defined with Recall()
to do this:
## data
res <- list()
str <- "USER|mshaffer|salt|salt.key|knox"
val <- "yo;*@];9u0>|>HpZS$F62hL6{lNJ@i"
## split to vector of names
nms <- strsplit(str, split = "\\|")[[1]]
## define recursive function
assignValue <- function(res, nms, val) {
if(length(nms) > 1) {
res[[nms[1]]] <- Recall(res[[nms[1]]], nms[-1], val)
} else {
res[[nms]] <- val
}
return(res)
}
assignValue(res, nms, val)
#> $USER
#> $USER$mshaffer
#> $USER$mshaffer$salt
#> $USER$mshaffer$salt$salt.key
#> $USER$mshaffer$salt$salt.key$knox
#> [1] "yo;*@];9u0>|>HpZS$F62hL6{lNJ@i"
NB: If all names and values to be assigned in the nested list are already available, this can also be done efficiently with rrapply()
in the rrapply
-package (extension of base rapply()
). First collect all names and values as rows in a data.frame and then call rrapply()
with how = "unmelt"
:
library(rrapply)
## one assignment per row
(dat <- as.data.frame(matrix(c(nms, val), nrow = 1, byrow = TRUE)))
#> V1 V2 V3 V4 V5 V6
#> 1 USER mshaffer salt salt.key knox yo;*@];9u0>|>HpZS$F62hL6{lNJ@i
rrapply(dat, how = "unmelt")
#> $USER
#> $USER$mshaffer
#> $USER$mshaffer$salt
#> $USER$mshaffer$salt$salt.key
#> $USER$mshaffer$salt$salt.key$knox
#> [1] "yo;*@];9u0>|>HpZS$F62hL6{lNJ@i"