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])}