更新字典而不覆盖现有的键值对?

时间:2017-03-02 18:58:54

标签: python dictionary

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

一般格式

<IP_1>
KEY_1=VALUE_1
KEY_2=VALUE_2

<IP_2>
KEY_1=VALUE_1
KEY_2=VALUE_2

实施例

192.168.1.1
USER_NAME=admin
PASSWORD=admin123

192.168.1.2
USER_NAME=user
PASSWORD=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_of_ip[ip] = slave_properties导致覆盖。如何防止'192.168.1.2'键覆盖第一个值?

6 个答案:

答案 0 :(得分:0)

试试这个:

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_properties = {}更改为应该的位置

您甚至可以删除slave_properties并单独使用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

答案 1 :(得分:0)

你没有在循环中执行slave_properties = {},所以当你认为你正在用

创建一个新的dict时,你指的是同一个dict对象
slave_properties[key] = value
dict_of_ip[ip] = slave_properties

答案 2 :(得分:0)

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

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_properties字典。因此,一个人的变化传播到另一个人。

答案 3 :(得分:0)

您可以选择正则表达方式与词典理解相结合:

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

working on ideone.com。这是相应的demo on regex101.com

答案 4 :(得分:0)

在识别出IP地址后,将public static node* FindMin(node* root){ //FindMax would be nearly identical node* minValue = root; while(node->Next){ if(node->Value < minValue->Value) minValue = node; } return minValue; } public static node* CountingSortArray(node* linklist){ node* root = linkedlist node* min = FindMin(linklist); node* max = FindMax(linklist); int[] counts = new int[max->Value - min->Value + 1]; while(root != NULL){ counts[root->Value] += 1; root = root->Next; } int i = 0; root = linkedlist; while(ptr != NULL){ if(counts[i] == 0) ++i; else{ root->Value = i; --count[i]; root = root->Next; } } } void push(node** head, int new_data){ node* newNode = new node(); newNode->Value = new_data; newNode->Next = (*head); (*head) = newNode; } void printList(node* root){ while(root != NULL){ printf(%d ", root->Value); root = root->Next; } printf("\n"); } int main(void){ node* myLinkedList = NULL; push(&head, 0); push(&head, 1); push(&head, 0); push(&head, 2); push(&head, 0); push(&head, 2); printList(myLinkedList); CountingSortArray(myLinkedList); printList(myLinkedList); } 的初始化移至右侧。这样,对于遇到的每一个,它都将为空(我也删除了slave_properties所不必要的初始化。)

dict_of_ip[ip]

输出:

from pprint import pprint

def generate_key_value_pair(filePath, sep='='):
    dict_of_ip = {}

    with open(filePath, "rt") as f:
        for line in f:
            line = line.strip()
            if line and line[0].isdigit():  # ip?
                slave_properties = {}  # initialize
                ip = line
            elif line and line[0].isupper():
                key_value = 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

result = generate_key_value_pair('ips.txt')
pprint(result)

答案 5 :(得分:0)

使用切片和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])}