首页 > 解决方案 > 如何将值附加到嵌套字典中的键并避免使用括号

问题描述

我有一个代码,它将下面文件中的这些行格式化为字典:

CommonChar pins Category General

CommonChar pins Contact Mark

CommonChar pins Description This is a 

CommonChar nails Category specific

CommonChar nails Contact John 

CommonChar pins Description This is a description 

最终的字典看起来像这样:

main_dict = {
'pins':
    {
        'Category': ['General'],
        'Contact': ['Mark'],
        'Description': ['This', 'is', 'a']
    },
'nails':
    {
        'Category': ['specific'],
        'Contact': ['Jon'],
        'Description': ['This', 'is', 'a', 'description']
    }}

我今天有这个代码来创建上面的字典:

filePath= os.path.join(dirName,eachFile)
fh=open(filePath, "r")
contents=fh.read()
items=re.findall("CommonChar.*$",contents,re.MULTILINE)
for x in items:
parts=x.split()
    if parts[1] in mainDict:
        if parts[2] in mainDict[parts[1]]:
            sys.exit("exit")
        else:
            mainDict[parts[1]].update({parts[2]:parts[3:]})
    else:
        mainDict[parts[1]]={}
        mainDict[parts[1]].update({parts[2]:parts[3:]})

如果我对代码的输入发生如下变化,那么我需要附加类似键的值:

CommonChar pins Category General

CommonChar pins Contact Mark

CommonChar pins Description This is a 

CommonChar pins Description secondLine

CommonChar nails Category specific

CommonChar nails Contact John 

CommonChar pins Description This is a description 

我需要从上面的行中得到这样的输出:

</br> 

也被添加到其中。

main_dict = {
'pins':
    {
        'Category': ['General'],
        'Contact': ['Mark'],
        'Description': ['This', 'is', 'a','</br>','secondLine']
    },
'nails':
    {
        'Category': ['specific'],
        'Contact': ['Jon'],
        'Description': ['This', 'is', 'a', 'description']
    }}

为此,我正在替换这一行:

sys.exit("exit")

有了这个:

mainDict[parts[1]][parts[2]].append(parts[3:])

但我得到这样的输出:

 main_dict = {
'pins':
    {
        'Category': ['General'],
        'Contact': ['Mark'],
        'Description': ['This', 'is', 'a',['secondLine']]
    },
'nails':
    {
        'Category': ['specific'],
        'Contact': ['Jon'],
        'Description': ['This', 'is', 'a', 'description']
    }}

那么如何避免将那些额外的 [ ] 添加到 secondLine 并添加

</br> 

在它面前?

标签: python

解决方案


这个怎么样?我对您的代码进行了一些更改:

  1. 在一个子句中打开并读取文件with,以保证它在完成后关闭。
  2. 将每个项目拆分为有意义的变量,以便更轻松地跟踪正在发生的事情。
  3. 使用 Python 风格的命名和标点而不是 Matlab ( main_dict = {}vs. mainDict={})。
  4. 用于在分配给每个组之前setdefault确保main_dict每个组都有一个空的字典(这通常比使用单独的分支在不存在时创建条目或在存在时更新它时更容易维护。)
  5. 用于.extend代替.append向有效负载列表添加更多项目。

/tmp/data1.txt

CommonChar pins Category General
CommonChar pins Contact Mark
CommonChar pins Description This is a 
CommonChar pins Description secondLine 

/tmp/data2.txt

CommonChar nails Category specific
CommonChar nails Contact John 
CommonChar nails Description This is a description

filesscript.py(更新为扫描变量中列出的多个文件)

import re, pprint

files = ['/tmp/data1.txt', '/tmp/data2.txt']

main_dict = {}
for filename in files:
    with open(filename, "r") as fh:
        contents = fh.read()
    items = re.findall("CommonChar.*$", contents, re.MULTILINE)
    for x in items:
        cc, group, topic, data = x.split(None, 3)
        data = data.split()
        group_dict = main_dict.setdefault(group, {'fileLocation': [filename]})
        if topic in group_dict:
            group_dict[topic].extend(['</br>'] + data)
        else:
            group_dict[topic] = data

pprint.pprint(main_dict)

输出

{'nails': {'Category': ['specific'],
           'Contact': ['John'],
           'Description': ['This', 'is', 'a', 'description'],
           'fileLocation': ['/tmp/data.txt']},
 'pins': {'Category': ['General'],
          'Contact': ['Mark'],
          'Description': ['This', 'is', 'a', '</br>', 'secondLine'],
          'fileLocation': ['/tmp/data.txt']}}

顺便说一句,如果您的代码遇到错误,它应该引发异常,而不是sys.exit()调用raise ValueError("Bad value in file").

您在对您的问题的评论中询问上述代码是否等同于您的代码,如下所示:

if parts[1] in mainDict: 
    if parts[2] in mainDict[parts[1]]: 
        mainDict[parts[1]][parts[2]].extend(['</br>']+parts[3:]) 
    else: 
        mainDict[parts[1]].update({parts[2]:parts[3:]}) 
else: 
    mainDict[parts[1]]={} 
    mainDict[parts[1]].update({parts[2]:parts[3:]})

它是,这里是它是如何工作的细分。首先,该行等效于,并且cc, group, topic, data = x.split(None, 3)等效于。然后下一行相当于. 进行这些替换会得到以下结果:groupparts[1]topicparts[2]dataparts[3:]

if group in mainDict: 
    if topic in mainDict[group]: 
        mainDict[group][topic].extend(['</br>'] + data) 
    else: 
        mainDict[group].update({topic: data]}) 
else: 
    mainDict[group]={} 
    mainDict[group].update({topic: data]})

接下来,我们注意到上面的代码等价于:

# next line sets groupDict=mainDict[group], creating it if needed
groupDict = mainDict.setdefault(group, {})
if topic in groupDict:
    groupDict[topic].extend(['</br>'] + data)
else:
    groupDict.update({topic: data]})

最后,我们注意到可以在第一次创建 groupDict 时存储文件名,这groupDict.update({topic: data]})相当于groupDict[topic] = data. 通过这些更改,我们得到:

groupDict = mainDict.setdefault(group, {'fileLocation': [filename]})
if topic in groupDict:
    groupDict[topic].extend(['</br>'] + data)
else:
    groupDict[topic] = data

除了拼写之外,这与我的解决方案的最后五行相同:

group_dict = main_dict.setdefault(group, {'fileLocation': [filename]})
if topic in group_dict:
    group_dict[topic].extend(['</br>'] + data)
else:
    group_dict[topic] = data

推荐阅读