当前位置: 首页 > 知识库问答 >
问题:

创建一个Python字典基于一个属性文件

梁德馨
2023-03-14

我想解析一个。属性文件的键和值放入python字典。这个我正在解析的属性文件使用以下语法(键和值是示例):

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()

生成的字典(outputDket)缺少两个键值对(key1.subkey1.subsubkey1=value e1,key1.subkey1.subsubkey2=value e2):

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

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

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

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

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

共有2个答案

应涵容
2023-03-14

一些观察结果:

  • 你想做的事情与Trie密切相关。您正在生成带有最终值的公共前缀

现在假设我们有一个名为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.u getitem_uu,key.split(“.”),trie)

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

在第一行中,我们为所有键创建Trie,所有值(leaves)都将是defaultdict。这意味着它可以扩展到任意深度(可以有任意多个子键)。

在第二行中,我们通过跟随键遍历Trie,直到最后一个键。使用key1.subkey1.subsubkey1=value e1作为示例,此代码将类似于

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

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

trie['key1']['subkey1']['subsubkey1'] = 'value1'
郝哲茂
2023-03-14

我复制了你的函数,测试了你的代码,并做了一些修改。下面的代码运行良好。

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'}}}}}}}

将您的OutputDket变量替换为storageDict.keys()并编写了一个样例main函数。试着自己运行它,看看它是否对你有用。

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

 类似资料:
  • Spring boot maven插件正在使用paketo builder构建图像。 我想做的是在这个构建器正在做的事情上添加另一个步骤。我已经创建了自己的构建包,并试图创建包含基本构建包的构建器。 我遇到的第一个问题是,当试图从builder.toml创建一个构建器时,会出现这样的错误: 另一个问题是,即使这样做有效,我想我仍然必须指定来自paketo:base的所有order.group。 是

  • 问题内容: 我需要加入 所有 PostgreSQL表并将它们转换成Python字典。数据库中有72个表。总列数大于 1600 。 我编写了一个简单的Python脚本,该脚本可以联接多个表,但是由于内存错误而无法联接所有表。在脚本执行期间,所有内存均被占用。然后,我在具有 128GB RAM和8个CPU 的新虚拟服务器上运行脚本。在lambda函数执行期间失败。 如何改进以下代码以执行 所有 表联接

  • 我希望在从application.yaml文件中读取一些属性后创建bean,然后将它们注入到其他bean中。如何做到这一点?

  • 本文向大家介绍数据字典属于哪一个用户的?相关面试题,主要包含被问及数据字典属于哪一个用户的?时的应答技巧和注意事项,需要的朋友参考一下 答案: 数据字典是属于’SYS’用户的,用户‘SYS’ 和 ’SYSEM’是由系统默认自动创建的

  • 基于dataframe列val_1值,查看其他列col_0-10标签前缀,然后创建另一列Mycl。 数据帧看起来像: 应用逻辑后所需的数据帧: 我是trid,但这不起作用:df['mycol']=df['col'df['val_1']。aType(str)] DDL生成DataFrame: 谢谢!

  • 我有两本字典Dict1和DICT2。Dict1中每个键的值如下所示: 但是Dict2由键组成,这些键是DICT1中的值。DICT2中的值是由元组组成的列表,如下所示。 我得到的当前输出是 我想要的输出应该是字典式的: