Updating a dictionary without overwriting an existing key-value pair?

I have an input file, as shown below, from which I can build a dictionary

General format

<IP_1>
KEY_1=VALUE_1
KEY_2=VALUE_2

<IP_2>
KEY_1=VALUE_1
KEY_2=VALUE_2

Example

192.168.1.1
USER_NAME=admin
PASSWORD=admin123

192.168.1.2
USER_NAME=user
PASSWORD=user123

The expected dictionary should look like this:

>>print dictionary_of_ip
{'192.168.1.1':{'USER_NAME'='admin','PASSWORD'='admin123'},
 '192.168.1.2':{'USER_NAME'='user','PASSWORD'='user123'}}

Essentially a dictionary in a dictionary

Below is my code:

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

I can get the first of the IP and their attributes as expected, but the second set of values ​​from the second IP address overwrites the first.

>>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_propertiescauses overwriting. How to prevent the replacement of values ​​from the '192.168.1.2'first key ?

+4
source share
6 answers

Try the following:

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

You where use the same (modified) dict. I did not change the logic of the code on purpose, just changed slave_properties = {}to where it should be

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
0

slave_properties = {} , dict, , dict

slave_properties[key] = value
dict_of_ip[ip] = slave_properties
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 . .

0

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

, ideone.com. regex101.com.

0

Just move the initialization slave_propertiesto the right after recognizing the IP address. This way, it will be empty for everyone you meet (I also deleted the unnecessary initialization that you had there 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)

Conclusion:

{'192.168.1.1': {'PASSWORD': 'admin123', 'USER_NAME': 'admin'},
 '192.168.1.2': {'PASSWORD': 'user123', 'USER_NAME': 'user'}}
0
source

Compact solution using slices and 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])}
0
source

Source: https://habr.com/ru/post/1671287/


All Articles