Mavjud kalit-qiymat juftligini qayta yozmasdan lug'atni yangilash?

Menda o'zimning lug'atingizni qurishingiz mumkin bo'lgan kirish fayli bor

Umumiy format


KEY_1=VALUE_1
KEY_2=VALUE_2


KEY_1=VALUE_1
KEY_2=VALUE_2

Misol

192.168.1.1
USER_NAME=admin
PASSWORD=admin123

192.168.1.2
USER_NAME=user
PASSWORD=user123

Kutilgan lug'at shunday bo'lishi kerak:

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

Asosan lug'atda lug'at

Quyida mening kodim:

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

Men birinchi IPni va ularning sifatlarini kutilgandek qabul qila olaman, lekin ikkinchi IP-qiymatlar to'plamining ikkinchi to'plamini birinchisiga yozib qo'yadi.

>>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 is causing the overwrite. How do I prevent the values from the '192.168.1.2' key overwriting the first one?

4
Ko'pchilik osonroq bo'larmidi?
qo'shib qo'ydi muallif Mangohero1, manba
qo'shib qo'ydi muallif Tadhg McDonald-Jensen, manba
agar ip dict_of_ip ichida emas: dict_of_ip [ip] = slave_properties buni bajarishi kerak ...
qo'shib qo'ydi muallif Jean-François Fabre, manba
shuning uchun siz aytmoqchisiz: agar kalit allaqachon mavjud bo'lsa, uni yangilamang, faqat yaratgin. Fikrni ko'ring, faqat dict-da allaqachon kalitni sinab ko'ring ...
qo'shib qo'ydi muallif Jean-François Fabre, manba
Maslahat: slave_properties o'zgaruvchining necha xil lug'ati uning ishlash muddati davomida ishlaydi?
qo'shib qo'ydi muallif jwodder, manba
@ Jan-Fransua Fabre, men sizning taklifingiz bilan harakat qildim, lekin men chiqishni "192.168.1.1": "192.168.1.2": "
qo'shib qo'ydi muallif Abhay Hegde, manba

6 javoblar

Agar Pythonning Yuqori Performans ma'lumotlaridan foydalansangiz, bu oson va samarali bo'ladi. Masalan, bu erda defaultdict o'rniga bir xil kod mavjud. o'z to'plam turini yaratish.

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. 

Keyinchalik aniqroq bo'lsa-da, har bir subdictionary uchun bir xil slave_properties lug'atini tahrirlashda xatolik yuz berdi. Shunday qilib, bitta o'zgarish boshqasiga tarqaladi.

0
qo'shib qo'ydi

Dict tushunish bilan birga regex usulini tanlashingiz mumkin:

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\d+\.\d+\.\d+\.\d+)[\n\r]
    USER_NAME=(?P.+)[\r\n]
    PASSWORD=(?P.+)
    """, 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'}}

Buni ideone.com ustida ishlash ga qarang. Mana, demo regex101.com .

0
qo'shib qo'ydi

Faqat slave_properties ning boshlanishini IP-manzil tan olinganidan so'ng o'ngga ko'chiring. Shunday qilib, duch kelgan har bir kishi uchun bo'sh qola boshlaydi (men sizning u erda bor bo'lgan keraksiz boshlovni olib tashladim, 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)

Chiqish:

{'192.168.1.1': {'PASSWORD': 'admin123', 'USER_NAME': 'admin'},
 '192.168.1.2': {'PASSWORD': 'user123', 'USER_NAME': 'user'}}
0
qo'shib qo'ydi

Siz loopda slave_properties = {} ni qilmaysiz, shuning uchun siz bir dict obyektiga murojaat qilasiz va siz yangi dict bilan

slave_properties[key] = value
dict_of_ip[ip] = slave_properties
0
qo'shib qo'ydi

Tillari va dictcomp yordamida kichik bir yechim:

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
qo'shib qo'ydi

Buni ko'ring:

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

Siz xuddi shu (o'zgartirilgan) dict dan foydalanishingiz mumkin. O'zingizning kod mantiqiy maqsadingizni o'zgartirmadim, faqat slave_properties = {} ni o'zgartirgan joyga o'zgartirdim.

Hatto slave_properties dan olib tashlashingiz mumkin va dict dan foydalaning

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
qo'shib qo'ydi
Python
Python
372 ishtirokchilar

Bu guruh python dasturlash tilini muhokama qilish uchun. Iltimos, o'zingizni hurmat qiling va faqat dasturlash bo'yicha yozing. Botlar mavzusini @botlarhaqida guruhida muhokama qling! FAQ: @PyFAQ Offtopic: @python_uz_offtopic

Python offtopic group !
Python offtopic group !
150 ishtirokchilar

@python_uz gruppasining offtop gruppasi. offtop bo'lsa ham reklama mumkin emas ) Boshqa dasturlash tiliga oid gruppalar @languages_programming