Reputation: 1782
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
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
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
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
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