Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在不覆盖现有键值对的情况下更新字典?_Python_Dictionary - Fatal编程技术网

Python 在不覆盖现有键值对的情况下更新字典?

Python 在不覆盖现有键值对的情况下更新字典?,python,dictionary,Python,Dictionary,我有一个如下的输入文件,我可以从中构建我的字典 通用格式 键1=值1 键2=值2 键1=值1 键2=值2 范例 192.168.1.1 用户名=管理员 密码=admin123 192.168.1.2 USER\u NAME=USER 密码=user123 预期的字典应如下所示: >>print dictionary_of_ip {'192.168.1.1':{'USER_NAME'='admin','PASSWORD'='admin123'}, '192.168.1.2':{

我有一个如下的输入文件,我可以从中构建我的字典

通用格式


键1=值1
键2=值2
键1=值1
键2=值2
范例

192.168.1.1
用户名=管理员
密码=admin123
192.168.1.2
USER\u NAME=USER
密码=user123
预期的字典应如下所示:

>>print dictionary_of_ip
{'192.168.1.1':{'USER_NAME'='admin','PASSWORD'='admin123'},
 '192.168.1.2':{'USER_NAME'='user','PASSWORD'='user123'}}
本质上是字典中的字典

下面是我的代码:

def generate_key_value_pair(filePath, sep='='):
    dict_of_ip = {}
    slave_properties = {}
    with open(filePath, "rt") as f:
        for line in f:
            stripped_line = line.strip()
            if stripped_line and stripped_line[0].isdigit():
                #print 'Found Ip'
                ip = stripped_line
                dict_of_ip[ip] = ''
            elif stripped_line and stripped_line[0].isupper():
                #print "Found attributes")
                key_value = stripped_line.split(sep)
                key = key_value[0].strip()
                value = key_value[1].strip()
                slave_properties[key] = value
                dict_of_ip[ip] = slave_properties

    return dict_of_ip
我能够按预期获得第一个IP及其属性,但是第二个IP的第二组值覆盖了第一个

>>print dict_of_ip
{'192.168.1.1': {'USER_NAME': 'user', 'PASSWORD': 'user123'},
 '192.168.1.2': {'USER_NAME': 'user', 'PASSWORD': 'user123'}}
dict\u of_ip[ip]=从属性
导致覆盖。如何防止来自
'192.168.1.2'
键的值覆盖第一个值?

尝试以下操作:

def generate_key_value_pair(filePath, sep='='):
    dict_of_ip = {}
    with open(filePath, "rt") as f:
        for line in f:
            stripped_line = line.strip()
            if stripped_line and stripped_line[0].isdigit():
                #print 'Found Ip'
                slave_properties = {}
                ip = stripped_line
                dict_of_ip[ip] = ''
            elif stripped_line and stripped_line[0].isupper():
                #print "Found attributes")
                key_value = stripped_line.split(sep)
                key = key_value[0].strip()
                value = key_value[1].strip()
                slave_properties[key] = value
                dict_of_ip[ip] = slave_properties

    return dict_of_ip
您可以使用相同的(修改的)
dict
。我不是故意更改您的代码逻辑,只是将
slave\u属性={}
更改为它应该位于的位置

您甚至可以删除您的
从属属性
,并单独使用
dict

def generate_key_value_pair(filePath, sep='='):
    dict_of_ip = {}
    with open(filePath, "rt") as f:
        for line in f:
            stripped_line = line.strip()
            if stripped_line and stripped_line[0].isdigit():
                #print 'Found Ip'
                ip = stripped_line
                dict_of_ip[ip] = {}
            elif stripped_line and stripped_line[0].isupper():
                #print "Found attributes")
                key_value = stripped_line.split(sep)
                key = key_value[0].strip()
                value = key_value[1].strip()
                dict_of_ip[ip][key] = value

    return dict_of_ip

在循环中不执行
slave\u properties={}
,因此,当您认为正在创建一个新的dict时,您引用的是同一个dict对象

slave_properties[key] = value
dict_of_ip[ip] = slave_properties

如果使用Python的高性能数据类型,这将变得更容易、更高效。例如,这里的代码与相同,而不是创建自己的集合类型

from collections import defaultdict

dict_of_ip = defaultdict(dict)   # This creates a dictionary of dictionaries for you.

ip = None  
for line in f:
    stripped_line = line.strip() 
    if stripped_line and stripped_line[0].isdigit():
        ip = stripped_line  # The value for the ip only changes if a new 
                            # IP is detected. Otherwise the algorithm proceeds
                            # with the older IP address to the nested dict. 

    elif stripped_line and stripped_line[0].isupper():
        key_value = stripped_line.split(sep)  
        key = key_value[0].strip()
        value = key_value[1].strip()
        dict_of_ip[ip][key] = value # IP set in the earlier if-loop. 

更具体地说,出现错误的原因是您正在为每个子词典编辑相同的
slave\u属性。因此,一种变化会传播到另一种变化

您可以选择一种正则表达式方式与dict理解相结合:

import re

string = """
192.168.1.1
USER_NAME=admin
PASSWORD=admin123

192.168.1.2
USER_NAME=user
PASSWORD=user123
"""

regex = re.compile(r"""
    ^
    (?P<ip>\d+\.\d+\.\d+\.\d+)[\n\r]
    USER_NAME=(?P<user>.+)[\r\n]
    PASSWORD=(?P<password>.+)
    """, re.MULTILINE | re.VERBOSE)

users = {match.group('ip'):
            {'USER_NAME': match.group('user'), 
            'PASSWORD': match.group('password')}
            for match in regex.finditer(string)}

print(users)
# {'192.168.1.2': {'USER_NAME': 'user', 'PASSWORD': 'user123'}, '192.168.1.1': {'USER_NAME': 'admin', 'PASSWORD': 'admin123'}}
重新导入
string=”“”
192.168.1.1
用户名=管理员
密码=admin123
192.168.1.2
USER\u NAME=USER
密码=user123
"""
regex=re.compile(r”“”
^
(?P\d+\.\d+\.\d+\.\d+[\n\r]
用户名=(?P.+)[\r\n]
密码=(?P.+)
“”,re.MULTILINE | re.VERBOSE)
用户={match.group('ip'):
{'USER_NAME':match.group('USER'),
“密码”:匹配.group('PASSWORD')}
对于regex.finditer(字符串)中的匹配项}
打印(用户)
#{'192.168.1.2':{'USER_NAME':'USER','PASSWORD':'user123'},'192.168.1.1':{'USER_NAME':'admin','PASSWORD':'admin123'}

看到了。这是相应的。

只要在识别出IP地址后将
从属性的初始化移到右侧即可。这样一来,遇到的每一个问题都会以空开始(我还删除了不必要的初始化,
dict\u of_ip[ip]

输出:

{'192.168.1.1':{'PASSWORD':'admin123','USER_NAME':'admin'},
'192.168.1.2':{'PASSWORD':'user123','USER_NAME':'USER'}

使用切片和dictcomp的紧凑解决方案:

with open("data.txt", "r") as f:
    f = [i.strip() for i in f.readlines()]
    ipdict = {ip: {'USER_NAME': user[10:], 'PASSWORD': password[9:]} 
              for ip, user, password in zip(f[0::4], f[1::4], f[2::4])}

如果ip不在dict\u of\u ip中:dict\u of\u ip[ip]=从属性
应该这样做……多个dict不是更容易吗?提示:变量
从属性
在其生命周期中引用了多少不同的字典?因此,您可以说:如果键已经存在,则不更新它,只创建它。请参阅我的评论,只需测试dict中已有的密钥…可能存在副本
with open("data.txt", "r") as f:
    f = [i.strip() for i in f.readlines()]
    ipdict = {ip: {'USER_NAME': user[10:], 'PASSWORD': password[9:]} 
              for ip, user, password in zip(f[0::4], f[1::4], f[2::4])}