I have a json:
{ 'a': ['c','d','e'],
'b': ['a','c','e'],
'c': ['a','b','d'],
....and so on
And also I have dictionary:
{'a':'abc','b':'cdf'}
Now, I want to change all these 'a' to 'abc' in the json file:
so, finally my json looks like:
{ 'abc': ['c','d','e'],
'cdf': ['abc','c','e'],
'c': ['a','cdf','d'],
....and so on
A = {'a' : ['b', 'c', 'd'],
'b' : ['a', 'c', 'd'],
'c' : ['a', 'b', 'd']}
B = {'a' : 'abc', 'b' : 'bcd'}
C = {}
for key in A.keys():
#Checking for key new value
if key in B.keys():
new_key = B[key]
else:
#If there is no new value for key
new_key = key
C[new_key] = []
for element in A[key]:
#Checking for new value of element
if element in B.keys():
new_element = B[element]
else:
#If there is no new value for element
new_element = element
C[new_key].append(new_element)
C is the modified version of A
You can also try this:
dict_1 = {
'a': ['c','d','e'],
'b': ['a','c','e'],
'c': ['a','b','d']
}
dict_2 = {'a':'abc','b':'cdf'}
for key in list(dict_1):
if key in dict_2:
dict_1[dict_2[key]] = dict_1.pop(key)
print(dict_1)
Output:
{'c': ['a', 'b', 'd'], 'abc': ['c', 'd', 'e'], 'cdf': ['a', 'c', 'e']}
{ dic.get(key, key): [dic.get(i, i) for i in value] for key, value in js.items() }
Where js is a dictionary representing your json and dic represents your dictionary {'a':'abc','b':'cdf'}
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
Goal
old_dct= {'A':'B','B':'C','C':'D','D':'E','F':'G','G':'K'}
new_dct = {'A':['B','C','D','E']
,'B':['C','D','E']
,'C':['D','E']
,'D':['E']
,'F':['G','K']
,'G':['K']}
The keys of new_dct is the same as old_dct. The values of new_dct is the value of old_dct based on keys. If the value is still in old_dct keys, then value should be update and the type is list. For example, 'A' is the key of old_dct and its value is B and B is the key of 'old_dct' and its value is C and so on. So the values of A in new_dct is ['B','C','D','E'].
old_dct= {'A':'B','B':'C','C':'D','D':'E','F':'G','G':'K'}
def get_values(letter, old_dict, values):
if letter in old_dict:
values.append(letter)
new_letter = old_dict[letter]
return get_values(new_letter, old_dict, values)
values.append(letter)
return values
new_dict = {}
for key, value in old_dct.items():
new_dict[key] = get_values(value, old_dct, [])
print(new_dict)
output
{'A': ['B', 'C', 'D', 'E'], 'B': ['C', 'D', 'E'], 'C': ['D', 'E'], 'D': ['E'], 'F': ['G', 'K'], 'G': ['K']}
you can try this:
old_dct= {'A':'B','B':'C','C':'D','D':'E','F':'G','G':'K'}
def itr_dct(key):
lst = []
g = key
while old_dct.get(key) and g:
g = old_dct.get(g)
lst.append(g)
return lst[:-1]
{k : itr_dct(k) for k,v in old_dct.items()}
Output:
{'A': ['B', 'C', 'D', 'E'],
'B': ['C', 'D', 'E'],
'C': ['D', 'E'],
'D': ['E'],
'F': ['G', 'K'],
'G': ['K']}
You could try a first approach (not too efficient because recalculates a lot of paths) like this:
old_dct= {'A':'B','B':'C','C':'D','D':'E','F':'G','G':'K'}
new_dct = {}
for l in old_dct:
current_path = []
k = l
while k in old_dct and k is not None:
k = old_dct.get(k,None)
if k:
current_path.append(k)
new_dct [l] = current_path
If you don't want to recalculate paths, you could check if the path of the current letter was already calculated:
old_dct= {'A':'B','B':'C','C':'D','D':'E','F':'G','G':'K'}
new_dct = {}
for l in old_dct:
if l not in new_dct :
current_path = []
k = l
while k in old_dct and k is not None:
k = old_dct.get(k,None)
if k:
current_path.append(k)
if k in new_dct :
current_path.extend([k]+new_dct [k])
break
new_dct [l] = current_path
def staggered_dict(d):
l = []
new_d = {}
for key, value in d.items():
temp_d = {**d}
temp_d.pop(key)
l.append(value)
while value in temp_d:
l.append(temp_d[value])
temp_d = {**temp_d}
value = temp_d.pop(value)
new_d[key] = l
l = []
return new_d
old_dct = {'A':'B','B':'C','C':'D','D':'E','F':'G','G':'K'}
new_dct = staggered_dict(old_dct)
print(new_dct)
Out:
{'A': ['B', 'C', 'D', 'E'], 'B': ['C', 'D', 'E'], 'C': ['D', 'E'], 'D': ['E'], 'F': ['G', 'K'], 'G': ['K']}
I need to create a dictionary structure in the below format.
list_1 = [1,2,3,4,5]
list_2 = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
list_3 = random.sample(list_2 , random.randint(0,len(list_2))
Loop as the len(list_1) and need to loop using list_2 and then using the random sample created using list_3, assigning each value of the list_3 as a value in the inner dictionary below, while iterating.
*Needed dictionary format:
my_dict = { 1: { 1: a,
2:b,
3,c},
2: { 1: 'd',
2: 'g'},
3: {1, 'e',
2, 'f',
3, 'g'}
.....
}*
My code:
list_1 = [1,2,3,4,5]
list_2 = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
list_4= []
j= 1
while i <= len(list_1):
list_3 = random.sample(list_2 , random.randint(0,len(list_2))
for k in list_3:
my_dict= { i: { j: k,
}
}
j+=1
i+=1
list_3 = random.sample(list_2 , random.randint(0,len(list_2))
list_4.append(my_dict)
The jth value should increment after every iterating of list_3 and keep adding a new jth key + value (k)
After the loop ends of list_3, another sample list (list_3) should be created and the above same repeats in the new ith key and gets added to the dictionary.
I am not getting the required result and need help if anyone can fix the code.
Thank you!
You're overwriting your my_dict in every iteration of the loop. You only need to add a new subdict with key i:
list_1 = [1,2,3,4,5]
list_2 = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
my_dict = {}
for i in list_1:
list_3 = random.sample(list_2 , random.randint(0,len(list_2)))
my_dict[i] = dict(enumerate(list_3, 1))
So, you have a list of keys and a list of values and you want to create a dictionary with one entry for each key, where the value for each key is a dictionary with a random selection from values as values and sequential numerical keys, starting at 1.
keys = [1, 2, 3, 4, 5]
values = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
result = {
k: {n: v
for n, v in enumerate(random.sample(values, random.randint(0, len(values))), 1)
}
for k in keys }
This:
defines a dictionary;
result= {}
with an entry for each key k in keys;
result= {k: {} for k in keys}
with each dictionary having keys and values from an enumeration starting at 1;
{n: v for n, v in enumerate([], 1)}
with the values being a random sample from values;
random.sample(values, _)
with a length between 0 and all items in values.
random.sample(random.randint(0, len(values)))
And Python allows you to just turn the enumeration into a dict directly:
result = {
k: dict(enumerate(random.sample(values, random.randint(0, len(values))), 1))
for k in keys }
you can try this:
import random
list_1 = [1,2,3,4,5]
list_2 = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
for i in list_1:
list_3 = random.sample(list_2 , random.randint(0,len(list_2)))
my_dict[i]=dict(enumerate(list_3,1))
print(my_dict)
I made a mistake in my question here (wrong requested input and expected output):
Comparing dicts, updating NOT overwriting values
I am not looking for this solution:
Combining 2 dictionaries with common key
So this question is not a duplicate
Problem statement:
requested input:
d1 = {'a': ['a'], 'b': ['b', 'c']}
d2 = {'b': ['c', 'd'], 'c': ['e','f']}
expected output (I don't care about the order of the keys / values!):
new_dict = {'a': ['a'], 'b': ['b', 'c', 'd'], 'c': ['e', 'f']}
The solution in Combining 2 dictionaries with common key
gives following output:
new_dict = {'a': ['a'], 'b': ['b', 'c', 'c', 'd'], 'c': ['e', 'f']}
I don't want the duplicates to be stored.
My solution (it works but it is not so efficient):
unique_vals = []
new_dict = {}
for key in list(d1.keys())+list(d2.keys()) :
unique_vals = []
try:
for val in d1[key]:
try:
for val1 in d2[key]:
if(val1 == val) and (val1 not in unique_vals):
unique_vals.append(val)
except:
continue
except:
new_dict[key] = unique_vals
new_dict[key] = unique_vals
for key in d1.keys():
for val in d1[key]:
if val not in new_dict[key]:
new_dict[key].append(val)
for key in d2.keys():
for val in d2[key]:
if val not in new_dict[key]:
new_dict[key].append(val)
Here is how I would go about it:
d1 = {'a': ['a'], 'b': ['b', 'c']}
d2 = {'b': ['c', 'd'], 'c': ['e','f']}
dd1 = {**d1, **d2}
dd2 = {**d2, **d1}
{k:list(set(dd1[k]).union(set(dd2[k]))) for k in dd1}
Produces the desired result.
I suggest using a default dictionary collection with a set as a default value.
It guarantees that all values will be unique and makes the code cleaner.
Talking about efficiecy it's O(n^2) by time.
from collections import defaultdict
d1 = {'a': ['a'], 'b': ['b', 'c']}
d2 = {'b': ['c', 'd'], 'c': ['e','f']}
new_dict = defaultdict(set)
for k, v in d1.items():
new_dict[k] = new_dict[k].union(set(v))
for k, v in d2.items():
new_dict[k] = new_dict[k].union(set(v))
Try this code. You can remove deep copy if modifications in the initial array are fine for you.
import copy
def merge(left, right):
res = copy.deepcopy(left)
for k, v in right.items():
res[k] = list(set(res[k]).union(v)) if k in res else v
return res
Simple if statement if you don't want to use a Set.
d3 = dict(d2)
for k,v in d1.items():
if k not in d3:
d3[k] = v
else:
for n in d1[k]:
if n not in d3[k]:
d3[k].append(n)
Problem
I have a hard time figuring out how to return a nested list from a recursive function. I have a nested structure, from which I want to return elements from each level.
Input
I have a structure similar to the following, where I however do not know the depth.
# Data
my_input = {'a': {'d':None, 'e':None, 'f':{'g':None}}, 'b':None, 'c':None}
Output
I need all possible levels output to a list of lists
# Desired output
[['a'], ['b'], ['c'], ['a', 'd'], ['a', 'e'], ['a', 'f'], ['a', 'f', 'g']]
What I have tried
This function does not work at all. It seems I am not able to get my head around how to return from a recursive function. Whenever I run through the function I end up either overwriting the output, or not having the correct information from the previous iteration. Any suggestions of how to write this function properly?
def output_levels(dictionary, output=None):
print(dictionary)
if not output:
output = []
if len(dictionary.keys()) == 1:
return output.append(dictionary.keys())
for key in dictionary.keys():
if not dictionary[key]:
output.append(key)
continue
output.append(output_levels(dictionary[key], output.append(key)))
return output
You could do:
my_input = {'a': {'d': None, 'e': None, 'f': {'g': None}}, 'b': None, 'c': None}
def paths(d, prefix=None):
if prefix is None:
prefix = []
for key, value in d.items():
if value is not None:
yield prefix + [key]
yield from paths(value, prefix=prefix + [key])
else:
yield prefix + [key]
print(sorted(paths(my_input), key=len))
Output
[['a'], ['b'], ['c'], ['a', 'd'], ['a', 'e'], ['a', 'f'], ['a', 'f', 'g']]
Simply we can do something like this:
dictionary = {
'a': {
'd': None,
'e': None,
'f': {
'g': None,
},
},
'b': None,
'c': None,
}
expected_output = [
['a'], ['b'], ['c'],
['a', 'd'], ['a', 'e'], ['a', 'f'],
['a', 'f', 'g'],
]
def get_levels(dictionary, parents=[]):
if not dictionary:
return []
levels = []
for key, val in dictionary.items():
cur_level = parents + [key]
levels.append(cur_level)
levels.extend(get_levels(val, cur_level))
return levels
output = get_levels(dictionary)
print(output)
assert sorted(output) == sorted(expected_output)
Slightly shorter recursive approach with yield:
my_input = {'a': {'d':None, 'e':None, 'f':{'g':None}}, 'b':None, 'c':None}
def get_paths(d, c = []):
for a, b in getattr(d, 'items', lambda :[])():
yield c+[a]
yield from get_paths(b, c+[a])
print(list(get_paths(my_input)))
Output:
[['a'], ['a', 'd'], ['a', 'e'], ['a', 'f'], ['a', 'f', 'g'], ['b'], ['c']]
I create a new dictionary from my_list. Check every item and add to dictionary as a new
key and any item is same for the key then add into same as key in its value
The problem is while a new key is created its item is not append to the value to for that key.
My code:
my_list = ['a', 'b', 'c', 'a', 'a', 'b']
my_dict = {}
for item in my_list:
if item in my_dict:
my_dict[item] = [item]
my_dict[item] = []
print my_dict
output looks like this:
{'a': [], 'c': [], 'b': []}
but I want it look like that:
{'a': ['a', 'a'], 'c': [], 'b': ['b']}
You're resetting the list for each item at the end of your for loop. Instead, try this:
for item in my_list:
# First time you see an item create an empty list
if item not in my_dict:
my_dict[item] = []
# Otherwise, add the item to the list
else:
my_dict[item].append( item )
This will give the desired output:
my_dict = dict(map(lambda x: (x, list((my_list.count(x)-1)*x)), my_list))
You can use Counter also
from collections import Counter
>>>{i:[i]*(j-1) for i,j in Counter(my_list).items()}
{'a': ['a', 'a'], 'c': [], 'b': ['b']}
You're always replacing the value in the dictionary by an empty list.
You should : add an item if the key is already present or create a new list for a new item
my_list = ['a', 'b', 'c', 'a', 'a', 'b']
my_dict = {}
for item in my_list:
if item in my_dict:
my_dict[item] += [item]
else:
my_dict[item] = [item]
print my_dict
my_list = ['a', 'b', 'c', 'a', 'a', 'b']
my_dict = {}
for item in my_list:
if item in my_dict:
my_dict[item] += [item]
else:
my_dict[item] = []
print my_dict
Output:
{'a': ['a', 'a'], 'c': [], 'b': ['b']}
for item in my_list:
if item in my_dict.keys():
my_dict[item].append(item)
else:
my_dict[item]=[]
or more simple:
for item in set(my_list):
my_dict[item]=[x]*(my_list.count(item)-1)
This should work.
You can add a list to the dict first by writing my_dict[item] = [] and then you can append to it
my_list = ['a', 'b', 'c', 'a', 'a', 'b']
my_dict = {}
for item in my_list:
if item not in my_dict:
my_dict[item] = []
else:
my_dict[item].append(item)
print my_dict