基于 .properties 文件制作 Python 字典

如何解决基于 .properties 文件制作 Python 字典

我想将 .properties-file 的键和值解析为 Python 字典。 我正在解析的 .properties-file 使用以下语法(键和值是示例):

key1.subkey1.subsubkey1=value1
key1.subkey1.subsubkey2=value2
key1.subkey2=value3
key2=value4

所以每个值对应一个键,由一个或多个用句点划分的级别组成。 目标是创建一个 Python 字典,其中每个键都是一个包含其值和子键的字典。字典应该是可递归迭代的,所以每一层都应该遵循相同的结构。

前面的例子应该产生以下类型的字典:

'subKeys': 
  'key1':
    'subKeys':
      'subkey1': 
        'subKeys':
          'subsubkey1': 
            'val': 'value1'
          'subsubkey2': 
            'val': 'value2'
      'subkey2': 
        'val': 'value3'
  'key2':
    'val': 'value4'

我在 python 中使用以下算法循环它:

def setKeyAndValue(storageDict,rowParts):
    keyParts = rowParts[0].split('.')
    if not keyParts[0] in outputDict:
        storageDict[keyParts[0]] = {}
    newObj = storageDict[keyParts[0]]
    for i in range(len(keyParts)):
        if i == len(keyParts)-1:
            # Reached the end of the key,save value to dictionary
            newObj["val"] = rowParts[1]
        else :
            # Not yet at the end of the key
            if "subKeys" not in newObj:
                newObj["subKeys"] = {}
            if keyParts[i+1] not in newObj["subKeys"]:
                newObj["subKeys"][keyParts[i+1]] = {}
            newObj = newObj["subKeys"][keyParts[i+1]]

f = open("FILEPATH.properties","r")
outputDict = {}
outputDict["subKeys"] = {}
outputDictSubKeys = outputDict["subKeys"]
for row in f:
    if not row.startswith('#') and not row.startswith('//'):
        parts = row.split('=',1)
        if  len(parts)== 2:
            setKeyAndValue(outputDictSubKeys,parts)  
f.close()

生成的字典(outputDict)缺少两个键值对(key1.subkey1.subsubkey1=value1, key1.subkey1.subsubkey2=value2):

'subKeys': 
  'key1':
    'subKeys':
      'subkey2': 
        'val': 'value3'
  'key2':
    'val': 'value4'

我很确定问题出在以下一行:

newObj = newObj["subKeys"][keyParts[i+1]]

我用循环的每次迭代替换字典中的 newObj。

有没有办法调整这个现有的算法以使其工作,如果没有,我应该如何重新开始?效率不是问题,属性文件不是很大。

解决方法

一些观察:

  • 您尝试做的事情与 Trie 密切相关。您正在生成具有最终值的通用前缀。
  • 对于嵌套结构,来自 functools 的内置 reduce 函数将变得非常有用。

解决方案

数据

现在假设我们有一个名为 data.properties 的文件,其结构如下

key1.subkey1.subsubkey1=value1
key1.subkey1.subsubkey2=value2
key1.subkey2=value3
key2=value4

代码

然后我们可以使用下面的代码

import functools
from collections import defaultdict
from pprint import pprint

if __name__ == '__main__':
    node = lambda: defaultdict(node)
    trie = node()

    with open("data.properties",'r') as file:
        for line in file.readlines():
            key,value = line.strip().split('=')
            functools.reduce(dict.__getitem__,key.split('.'),trie)

            val = (functools.reduce(lambda d,key: d.get(key),key.split('.')[:-1],trie))
            val[key.split('.')[-1]] = value

    pprint(trie)

输出

生成以下输出

defaultdict(<function <lambda> at 0x000002054579EF70>,{'key1': defaultdict(<function <lambda> at 0x000002054579EF70>,{'subkey1': defaultdict(<function <lambda> at 0x000002054579EF70>,{'subsubkey1': 'value1','subsubkey2': 'value2'}),'subkey2': 'value3'}),'key2': 'value4'})

defaultdict 可以忽略的地方,只要键在字典中。如果要删除defaultdict属性,可以使用这个函数

def defaultdict_to_dict(data):
    """ Convert a nested defaultdict to a normal dictionary.  """
    if isinstance(data,defaultdict):
        data = dict(data)
    if isinstance(data,dict):
        for k,v in data.items():
            data[k] = defaultdict_to_dict(v)
    return data

并使用 pprint(defaultdict_to_dict(trie)) 调用它。 这将输出

{'key1': {'subkey1': {'subsubkey1': 'value1','subsubkey2': 'value2'},'subkey2': 'value3'},'key2': 'value4'}

说明

大部分魔法发生在以下两行

1) functools.reduce(dict.__getitem__,trie)

2) val = (functools.reduce(lambda d,trie))

在第一行中,我们为所有键创建了 Trie,所有值(叶子)都将是 defaultdict。这意味着它可以扩展任意深度(拥有任意数量的子键)。

在第二行中,我们按照键遍历 Trie,直到最后一个键。以key1.subkey1.subsubkey1=value1为例,这段代码将类似于

val = trie['key1']['subkey1']

其中下一行 (val[key.split('.')[-1]] = value) 等于

trie['key1']['subkey1']['subsubkey1'] = 'value1'
,

我复制了您的函数并测试了您的代码并进行了一些更改。下面的代码工作正常。

def setKeyAndValue(storageDict,rowParts):
    print rowParts
    keyParts = rowParts[0].split('.')
    if not keyParts[0] in storageDict.keys():
            storageDict[keyParts[0]] = {}
    newObj = storageDict[keyParts[0]]
    for i in range(len(keyParts)):
            if i == len(keyParts)-1:
                    # Reached the end of the key,save value to dictionary
                    newObj["val"] = rowParts[1]
            else :
                    # Not yet at the end of the key
                    if "subKeys" not in newObj:
                            newObj["subKeys"] = {}
                    if keyParts[i+1] not in newObj["subKeys"]:
                            newObj["subKeys"][keyParts[i+1]] = {}
                    newObj = newObj["subKeys"][keyParts[i+1]]



def main():
    input  = [
            'key1.subkey1.subsubkey1=value1','key1.subkey1.subsubkey2=value2','key1.subkey2=value3','key2=value4'
    ]
    ans = {}
    ans1 = {
            'subKeys': ans
    }

    for row in input:
            parts = row.split('=',1)
            setKeyAndValue(ans,parts)
    print ans1

main()

输出如下:

{'subKeys': {'key2': {'val': 'value4'},'key1': {'subKeys': {'subkey2': {'val': 'value3'},'subkey1': {'subKeys': {'subsubkey1': {'val': 'value1'},'subsubkey2': {'val': 'value2'}}}}}}}

OutputDict 替换您的 storageDict.keys() 变量并编写了一个示例主函数。尝试自己运行它,看看它是否适合您。

我认为您的 OutputDict 仅包含 subKeys 键,因此条件将始终为真,您将用空白字典替换之前添加的字典。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res