Home > Blockchain >  Using R, how to create a function that assigns a value to a deeply nested list based on a string ind
Using R, how to create a function that assigns a value to a deeply nested list based on a string ind

Time:09-30

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