如何创建函数:基于嵌套深度字符串为深层嵌套列表赋值?
问题描述
背景
我正在开发一个解析器,用于处理类INI格式的文件,示例内容如下:
[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
需求
现有一个空列表:
res = list()
还有一个字符串str用于指定赋值的嵌套层级:
# 对应 [USER][mshaffer] ... salt[^salt.key][knox] str = "USER|mshaffer|salt|salt.key|knox" val = "yo;*@];9u0>|>HpZS$F62hL6{lNJ@i"
需要实现一个函数assignValue,接收str、val、res三个参数,返回完成赋值后的嵌套列表。函数框架如下:
assignValue = function(str, val, res) { # 检查对应层级是否存在,不存在则初始化为list() # 在指定层级赋值val return(res) }
要求尽可能避免使用eval(parse(text=x)),目前已有硬编码的10层级循环实现,寻求base-R原生解决方案。
硬编码的方式可以直接实现所需嵌套结构:
res[["USER"]][["mshaffer"]][["salt"]][["salt.key"]][["knox"]] = "yo;*@];9u0>|>HpZS$F62hL6{lNJ@i"
最终生成的嵌套列表结构如下:
$USER $USER$mshaffer $USER$mshaffer$salt $USER$mshaffer$salt$salt.key $USER$mshaffer$salt$salt.key$knox [1] "yo;*@];9u0>|>HpZS$F62hL6{lNJ@i"
解决方案
可以通过循环遍历层级路径的方式实现,无需递归或硬编码多层结构,具体代码如下:
assignValue = function(str, val, res) { # 拆分层级字符串为路径向量 path = strsplit(str, "\\|")[[1]] # 从根列表开始,逐步深入 current = res # 遍历除最后一个节点外的所有层级,创建嵌套列表 for (level in path[-length(path)]) { if (!exists(level, envir = current)) { current[[level]] = list() } current = current[[level]] } # 为最后一个节点赋值 current[[path[length(path)]]] = val # 返回修改后的根列表 res }
测试示例
res = list() str = "USER|mshaffer|salt|salt.key|knox" val = "yo;*@];9u0>|>HpZS$F62hL6{lNJ@i" res = assignValue(str, val, res) print(res)
输出结果将和硬编码实现的嵌套结构完全一致。
说明
- 用
strsplit拆分层级字符串,得到每个节点的名称向量; - 循环遍历路径中的前n-1个节点,检查当前层级是否存在对应列表,不存在则创建;
- 每次循环后将当前指针移动到下一层级;
- 最后将值赋给路径的最后一个节点;
- 全程使用base-R函数,完全避免
eval,且支持任意深度的嵌套层级。
内容的提问来源于stack exchange,提问作者mshaffer
相关产品推荐
相关产品推荐

