AhmFM
AhmFM

Reputation: 1782

Form a python dictionary based on pattern matched keys and values in file

I am trying to create a dictionary with a file containing text based on a matched pattern. Lines containing key_str should become keys and subsequent lines should become values associated with those keys in the dictionary.

File:

ml1
/core
/home

ml2
/var
/home
/lib

cpuml1
/home
/root
/raid

Expected Output

my_dict: {ml1: ['/core','/home'], ml2: ['/var','/home','/lib'], cpuml1: ['/home','/root','/raid']}

Code:

d = {}
key_str = "ml"
val_str = ""
key_list = []
val_list = []
with open(homedir+'/backup/file2dict.result') as file2dict:
    for line in file2dict:
        words=line.split()
        for aWord in words:
            if key_str in aWord:
                key_list.append(aWord)
                print(key_list)
            else:
                val_list.append(aWord)
    print("this is formed dictionary", d)

Upvotes: 1

Views: 197

Answers (4)

Ryan Laursen
Ryan Laursen

Reputation: 647

Whenever you encounter a new key, add existing val_list to last key and wipe val_list.

key_str = "ml"
val_str = ""
val_list = []
key = ''
d = {}
with open(homedir + '/backup/file2dict.result') as file2dict:
    for line in file2dict:
        words = line.split()
        for aWord in words:
            if key_str in aWord:
                if key:
                    d[key] = val_list
                    val_list = []
                    key = aWord
                else:
                    key = aWord
            else:
                val_list.append(aWord)
    d[key] = val_list

    print("this is formed dictionary", d)

Upvotes: 1

PieCot
PieCot

Reputation: 3639

You could simplify your code:

key_str = "ml"
result = {}
curr_key = None
with open('file2dict.result', 'r') as file2dict:
    for line in filter(lambda l: l != '', map(str.strip, file2dict)):
        if key_str in line:
            curr_key = line
            result[curr_key] = []
        elif curr_key is not None:
            result[curr_key].append(line)
        else:
            print("Value without a key: {}".format(line))

Here filter(lambda l: l != '', map(str.strip, file2dict)) id used to filter out empty lines; moreover you can use a dict (result) to collect lines.

If you cannot have keys without any following valid line in your input file (or if you want to skip them), you can use setdefault for your dict:

key_str = "ml"
result = {}
curr_key = None
with open('file2dict.result', 'r') as file2dict:
    for line in filter(lambda l: l != '', map(str.strip, file2dict)):
        if key_str in line:
            curr_key = line
        elif curr_key is not None:
            result.setdefault(curr_key, []).append(line)
        else:
            print("Value without a key: {}".format(line))

Upvotes: 0

beroe
beroe

Reputation: 12316

Here is one way to do it:

#! /usr/bin/env python3
keystr="ml"
k=''
d = {}
with open ("testp.txt") as file2dict:
    for line in file2dict:
        li = line.strip()
        # This uses your keystr, but you could say if not line.startswith("/"):
        if keystr in li:  
            k = li
        elif li and k:
            d[k] = d.get(k,[]) + [li]
        
print(d)

Upvotes: 0

TigerhawkT3
TigerhawkT3

Reputation: 49318

Assuming that input format is correct, with double linefeeds between each block, each block starting with a key name, each following line in a block being a value for that key, and each key being unique in the file, as well as assuming that you meant ['/var','/home', '/lib'] for the ml2 key, then the result can be created with a comprehension:

with open(file) as f:
    result = {key:lst for key, *lst in (block.split('\n') for block in f.read().split('\n\n'))}

Testing with a multiline string instead of a file:

>>> s = '''ml1
... /core
... /home
...
... ml2
... /var
... /home
... /lib
...
... cpuml1
... /home
... /root
... /raid'''
>>> {key:lst for key, *lst in (block.split('\n') for block in s.split('\n\n'))}
{'ml1': ['/core', '/home'], 'ml2': ['/var', '/home', '/lib'], 'cpuml1': ['/home', '/root', '/raid']}

Upvotes: 0

Related Questions