open files for each of many dictionaries in python - python

I have two main dictionaries:
dict_main1 = {}
dict_main2 = {}
And then I open many dictionaries (below only 6 of 26 I have) which store the values of the main dictionaries depending on one particular string:
string1 = {}
string2 = {}
string3 = {}
string4 = {}
string5 = {}
string6 = {}
for key, value in dict_main1.items():
if 'string1' in key:
string1[key] = dict_main1[key]
elif 'string2' in key:
string2[key] = dict_main1[key]
elif 'string3' in key:
string3[key] = dict_main1[key]
......
for key, value in dict_main2.items():
if 'string4' in key:
string4[key] = dict_main2[key]
elif 'string5' in key:
string5[key] = dict_main2[key]
elif 'string6' in key:
string6[key] = dict_main2[key]
......
How can I open a file for each strin#={} in a pythonic way?. I would like to avoid doing it one by one (as in the example below):
FI = open ('string1', w)
for key, value in string1.items():
OUT = key + '\n' + value + '\n'
FI.write(OUT)

First of all you don't need 99999 dicts, just use one with dicts inside it.
for example:
from collections import collections.defaultdict
my_keys = ['str1', 'str2', ....]
container_dict = defaultdict(dict)
for key, value in dict_main.items():
for k in my_keys:
if k in key:
container_dict[k][key] = value
now for the files, just use for:
for string, strings_dict in container_dict:
with open(string, "wb") as f:
# format string dict... and save it
i didn't run this code, so maybe there are some bugs, but i suppose it ok

It might be useful to use a single dictionary data structure rather than maintaining 26 different dictionaries.
def split_dict(d, corpus):
dicts = {{} for w in corpus}
for k, v in d.items():
word = next(filter(lambda w: w in k, corpus))
dicts[word][k] = v
return dicts
dict_main = {...}
corpus = [f'string{i}' for i in range(1, 4)]
dict_split = split_dict(dict_main, corpus)
Now, just loop through dict_split:
for word, d in dict_split:
with open(word, 'w') as f:
for key, value in d.items():
f.write(f'{key}\n{value}\n')

Related

Trying to pull all the values that matches the key into one key

I've been trying to simply just pull all the values that matches the key into one key. I can't wrap my head around on how to do this. Please help.
list_dir = ['192586_Sample_010_Test.pdf', '192586_Sample_020_Test.pdf', '192586_Sample_050_Test.pdf', '192120_Sample_020_Test.pdf', '192120_Sample_050_Test.pdf', '192163_Sample_010_Test.pdf', '192163_Sample_020_Test.pdf', '192145_Sample_010_Test.pdf', '192145_Sample_020_Test.pdf', '192145_Sample_050_Test.pdf', '192051_Sample_010_Test.pdf', '192051_Sample_020_Test.pdf', '192051_Sample_050_Test.pdf']
dict = {}
match = []
for i in list_dir:
match.append((i.split("_", 1)[-2]))
for i in match:
for x in list_dir:
if i in x:
dict[i] = list_dir
print(dict)
Output I'm looking for is
{'192586': '192586_Sample_010_Test.pdf', '192586_Sample_020_Test.pdf', '192586_Sample_050_Test.pdf',
'192120': '192120_Sample_020_Test.pdf', '192120_Sample_050_Test.pdf',
'192163': '192163_Sample_010_Test.pdf', '192163_Sample_020_Test.pdf',
'192145': '192145_Sample_010_Test.pdf', '192145_Sample_020_Test.pdf', '192145_Sample_050_Test.pdf',
'192051': '192051_Sample_010_Test.pdf', '192051_Sample_020_Test.pdf', '192051_Sample_050_Test.pdf'}
Just extract the key from the string and check if it's in the dict or not. If so append to the list otherwise create a new list.
Like this:
dct = {}
for i in list_dir:
key = i.split("_")[0]
if key in dct:
dct[key].append(i)
else:
dct[key] = [i]
print(dct)

Get specific key of a nested iterable and check if its value exists in a list

I am trying to access a specific key in a nest dictionary, then match its value to a string in a list. If the string in the list contains the string in the dictionary value, I want to override the dictionary value with the list value. below is an example.
my_list = ['string1~', 'string2~', 'string3~', 'string4~', 'string5~', 'string6~']
my_iterable = {'A':'xyz',
'B':'string6',
'C':[{'B':'string4', 'D':'123'}],
'E':[{'F':'321', 'B':'string1'}],
'G':'jkl'
}
The key I'm looking for is B, the objective is to override string6 with string6~, string4 with string4~, and so on for all B keys found in the my_iterable.
I have written a function to compute the Levenshtein distance between two strings, but I am struggling to write an efficient ways to override the values of the keys.
def find_and_replace(key, dictionary, original_list):
for k, v in dictionary.items():
if k == key:
#function to check if original_list item contains v
yield v
elif isinstance(v, dict):
for result in find_and_replace(key, v, name_list):
yield result
elif isinstance(v, list):
for d in v:
if isinstance(d, dict):
for result in find_and_replace(key, d, name_list):
yield result
if I call
updated_dict = find_and_replace('B', my_iterable, my_list)
I want updated_dict to return the below:
{'A':'xyz',
'B':'string6~',
'C':[{'B':'string4~', 'D':'123'}],
'E':[{'F':'321', 'B':'string1~'}],
'G':'jkl'
}
Is this the right approach to the most efficient solution, and how can I modify it to return a dictionary with the updated values for B?
You can use below code. I have assumed the structure of input dict to be same throughout the execution.
# Input List
my_list = ['string1~', 'string2~', 'string3~', 'string4~', 'string5~', 'string6~']
# Input Dict
# Removed duplicate key "B" from the dict
my_iterable = {'A':'xyz',
'B':'string6',
'C':[{'B':'string4', 'D':'123'}],
'E':[{'F':'321', 'B':'string1'}],
'G':'jkl',
}
# setting search key
search_key = "B"
# Main code
for i, v in my_iterable.items():
if i == search_key:
if not isinstance(v,list):
search_in_list = [i for i in my_list if v in i]
if search_in_list:
my_iterable[i] = search_in_list[0]
else:
try:
for j, k in v[0].items():
if j == search_key:
search_in_list = [l for l in my_list if k in l]
if search_in_list:
v[0][j] = search_in_list[0]
except:
continue
# print output
print (my_iterable)
# Result -> {'A': 'xyz', 'B': 'string6~', 'C': [{'B': 'string4~', 'D': '123'}], 'E': [{'F': '321', 'B': 'string1~'}], 'G': 'jkl'}
Above can has scope of optimization using list comprehension or using
a function
I hope this helps and counts!
In some cases, if your nesting is kind of complex you can treat the dictionary like a json string and do all sorts of replacements. Its probably not what people would call very pythonic, but gives you a little more flexibility.
import re, json
my_list = ['string1~', 'string2~', 'string3~', 'string4~', 'string5~', 'string6~']
my_iterable = {'A':'xyz',
'B':'string6',
'C':[{'B':'string4', 'D':'123'}],
'E':[{'F':'321', 'B':'string1'}],
'G':'jkl'}
json_str = json.dumps(my_iterable, ensure_ascii=False)
for val in my_list:
json_str = re.sub(re.compile(f"""("[B]":\\W?")({val[:-1]})(")"""), r"\1" + val + r"\3", json_str)
my_iterable = json.loads(json_str)
print(my_iterable)

Change Keys in dictionary

I have a dictionary:
d = {1:[9,9,9],2:[8,8,8],3:[7,7,7]}
and a list of keys :
newkeylist = [4,2,3]
Now i want check the keys in the dict with the content in the list. If they are different i want to replace the key in the dict with the one in the list.
for i in range(len(newkeylist)):
if d.key()[i] != newkeylist[i]:
d.key()[i] = newkeylist[i]
try something like this
d = {1:[9,9,9],2:[8,8,8],3:[7,7,7]}
newkeylist = [4,2,3]
d_copy = d.copy()
for i, (k, v) in enumerate(d_copy.items()):
if k != newkeylist[i]:
d[newkeylist[i]] = v
del d[k]
but as #jonrsharpe said, it's not an ordered dict: the output is random

Recursively accessing paths and values of a nested dictionary

In Python 2.7, how does one dynamically access and print out the keys and values of a nested dictionary? Here's a nonsensical example: https://jsoneditoronline.org/?id=da7a486dc2e24bf8b94add9f04c71b4d
Normally, I would do something like:
import json
json_sample = 'sample_dict.json'
json_file = open(json_sample, 'r')
json_data = json.load(json_file)
items = json_data['sample_dict']
for item in items:
dict_id = item['dict_id']
person = item['person']['person_id']
family = item['family']['members']
print dict_id
print person
print family
I can hard code it like this and it'll give me desirable results, but how would I access each of the keys and values dynamically so that:
The first row just prints the keys (dict_id, person['person_id'], person['name'], family['members']['father'])
The second row prints the values respectively (5, 15, "Martin", "Jose")
The end result should be in a CSV file.
You can use a recursive visitor/generator which returns all the path/value pairs of the leaves:
def visit_dict(d, path=[]):
for k, v in d.items():
if not isinstance(v, dict):
yield path + [k], v
else:
yield from visit_dict(v, path + [k])
(replace the yield from ... with the appropriate equivalent if using Python < 3.4)
Getting the keys:
>>> ','.join('/'.join(k) for k, v in visit_dict(json_data['sample_dict'][0]))
'dict_id,person/person_id,person/name,person/age,family/person_id,family/members/father,family/members/mother,family/members/son,family/family_id,items_id,furniture/type,furniture/color,furniture/size,furniture/purchases'
and the values:
>>> ','.join(str(v) for k, v in visit_dict(json_data['sample_dict'][0]))
'5,15,Martin,18,20,Jose,Maddie,Jerry,2,None,Chair,Brown,Large,[]'

Combine Python dictionaries that have the same Key name

I have two separate Python List that have common key names in their respective dictionary. The second list called recordList has multiple dictionaries with the same key name that I want to append the first list clientList. Here are examples lists:
clientList = [{'client1': ['c1','f1']}, {'client2': ['c2','f2']}]
recordList = [{'client1': {'rec_1':['t1','s1']}}, {'client1': {'rec_2':['t2','s2']}}]
So the end result would be something like this so the records are now in a new list of multiple dictionaries within the clientList.
clientList = [{'client1': [['c1','f1'], [{'rec_1':['t1','s1']},{'rec_2':['t2','s2']}]]}, {'client2': [['c2','f2']]}]
Seems simple enough but I'm struggling to find a way to iterate both of these dictionaries using variables to find where they match.
When you are sure, that the key names are equal in both dictionaries:
clientlist = dict([(k, [clientList[k], recordlist[k]]) for k in clientList])
like here:
>>> a = {1:1,2:2,3:3}
>>> b = {1:11,2:12,3:13}
>>> c = dict([(k,[a[k],b[k]]) for k in a])
>>> c
{1: [1, 11], 2: [2, 12], 3: [3, 13]}
Assuming you want a list of values that correspond to each key in the two lists, try this as a start:
from pprint import pprint
clientList = [{'client1': ['c1','f1']}, {'client2': ['c2','f2']}]
recordList = [{'client1': {'rec_1':['t1','s1']}}, {'client1': {'rec_2':['t2','s2']}}]
clientList.extend(recordList)
outputList = {}
for rec in clientList:
k = rec.keys()[0]
v = rec.values()[0]
if k in outputList:
outputList[k].append(v)
else:
outputList[k] = [v,]
pprint(outputList)
It will produce this:
{'client1': [['c1', 'f1'], {'rec_1': ['t1', 's1']}, {'rec_2': ['t2', 's2']}],
'client2': [['c2', 'f2']]}
This could work but I am not sure I understand the rules of your data structure.
# join all the dicts for better lookup and update
clientDict = {}
for d in clientList:
for k, v in d.items():
clientDict[k] = clientDict.get(k, []) + v
recordDict = {}
for d in recordList:
for k, v in d.items():
recordDict[k] = recordDict.get(k, []) + [v]
for k, v in recordDict.items():
clientDict[k] = [clientDict[k]] + v
# I don't know why you need a list of one-key dicts but here it is
clientList = [dict([(k, v)]) for k, v in clientDict.items()]
With the sample data you provided this gives the result you wanted, hope it helps.

Categories

Resources