Setting dictionary property value to be the same as a previous value - python

I have a dictionary which I'd like to create a key/value pair where the value is the same as a previous property.
Is there a way I can assign property2's value to be the same as property1 without repeating myself?
obj = {
'property1': 'abc',
'property2': 'abc'
}
I tried this:
obj = {
'property1': 'abc',
'property2': obj['property1']
}
But that is referencing obj before it's assigned.

u can store the value in a variable first and then assign it like:
value = 'abc'
obj = {
'property1': value,
'property2': value
}

If you want to assign a value to a dictionary, you can do it in a few ways:
List Comprehension:
d = {a:'abc' for a in list('abcdefghijk')}
This will assign 'abc' to all keys in the dictionary.
The output of this will be:
{'a': 'abc', 'b': 'abc', 'c': 'abc', 'd': 'abc', 'e': 'abc', 'f': 'abc', 'g': 'abc', 'h': 'abc', 'i': 'abc', 'j': 'abc', 'k': 'abc'}
Assign to variable:
(like Marcos highlighted in earlier post)
value = 'abc'
d = {a:value for a in list('abcdefghijk')}
Same result:
{'a': 'abc', 'b': 'abc', 'c': 'abc', 'd': 'abc', 'e': 'abc', 'f': 'abc', 'g': 'abc', 'h': 'abc', 'i': 'abc', 'j': 'abc', 'k': 'abc'}

Related

Converting dictionaries in a nested dictionary

I'm trying to convert all values of some dictionaries that are nested in another dictionary.
I want to convert:
{0: {'n': 1}, 1: {'s': 0, 'n': 2}, 2: {'s': 1}}
To this:
{0: {'n': '?'}, 1: {'s': '?', 'n': '?'}, 2: {'s': '?'}}
I tried this:
for key, value in new_dictt:
new_dictt[key][value] = '?'
But it did not work. I've been googling but have not found a way to convert all values of all dictionaries within another dictionary.
Here we go:
old_dict = {0: {'n': 1}, 1: {'s': 0, 'n': 2}, 2: {'s': 1}}
new_dict = {key: {k: '?' for k in dct} for key, dct in old_dict.items()}
print(new_dict)
Which yields
{0: {'n': '?'}, 1: {'s': '?', 'n': '?'}, 2: {'s': '?'}}
This uses two nested dict comprehensions.

Calculating min difference between two dictionaries

I'm trying to calculate difference between two dictionaries to return a specific value.
I've entered different values which should return different results, but the result remains unchanged.
diets = {"normal" : {'p': '32.50', 'c': '60', 'f': '40.86'},
"oncology" : {'p': '35', 'c': '52.50', 'f': '37.63'},
"cardiology" : {'p': '32.50', 'c': '30', 'f': '26.88'},
"diabetes" : {'p': '20', 'c': '27.50', 'f': '27.95'},
"kidney" : {'p': '15', 'c': '55', 'f': '23.65'}}
amounts = {'p': p, 'c': c, 'f': f}
value = { k : diets[k] for k in set(diets) - set(amounts) }
calculate_error = min(value)
print(calculate_error)
When i input 32, 60 and 40, the returned result should be normal, but oncology is returned instead
You should look at the values you are creating when you do this:
set(diets)
This is just a list of keys.
{'cardiology', 'diabetes', 'kidney', 'normal', 'oncology'}
When you subtract the other list of keys, you just get the original list because no values are in common.
You need to actually step through the items and do the subtraction to get the differences. Then you can find the sum of the diffs and the min of that sum.
One way would be:
diets = {"normal" : {'p': '32.50', 'c': '60', 'f': '40.86'},
"oncology" : {'p': '35', 'c': '52.50', 'f': '37.63'},
"cardiology" : {'p': '32.50', 'c': '30', 'f': '26.88'},
"diabetes" : {'p': '20', 'c': '27.50', 'f': '27.95'},
"kidney" : {'p': '15', 'c': '55', 'f': '23.65'}}
amounts = {'p': 32., 'c': 60., 'f': 40.}
mins = [(diet, sum([abs(amounts[k] - float(d[k])) for k in amounts])) for diet, d in diets.items()]
the_min = min(mins, key = lambda x: x[1])
mins will be:
[('normal', 1.3599999999999994),
('oncology', 12.869999999999997),
('cardiology', 43.620000000000005),
('diabetes', 56.55),
('kidney', 38.35)]
the_min will be:
('normal', 1.3599999999999994)
It looks you totally confused what value would be
>>> diets = {"normal" : {'p':'32.50', 'c':'60', 'f':'40.86'},
... "oncology" : {'p':'35', 'c':'52.50', 'f':'37.63'},
... "cardiology" : {'p':'32.50', 'c':'30', 'f':'26.88'},
... "diabetes" : {'p':'20', 'c':'27.50', 'f':'27.95'},
... "kidney" : {'p':'15', 'c':'55', 'f':'23.65'}}
>>> set(diets)
{'kidney', 'cardiology', 'oncology', 'normal', 'diabetes'}
>>> amounts = {'p':32, 'c':60, 'f':40}
>>> set(amounts)
{'c', 'f', 'p'}
>>> set(diets) - set(amounts)
{'cardiology', 'diabetes', 'kidney', 'oncology', 'normal'}
>>> value = { k : diets[k] for k in set(diets) - set(amounts) }
>>> value
{'cardiology': {'p': '32.50', 'c': '30', 'f': '26.88'},
'diabetes': {'p': '20', 'c': '27.50', 'f': '27.95'},
'kidney': {'p': '15', 'c': '55', 'f': '23.65'},
'oncology': {'p': '35', 'c': '52.50', 'f': '37.63'},
'normal': {'p': '32.50', 'c': '60', 'f': '40.86'}}
>>> min(value)
'cardiology'
that said I would expect that you to get cardiology, i.e. the min from diets.keys()
That said, note that the values in the diets are str, e.g. '32.50', You will need to convert these before any calculations.

Constructing a nested dictionary based on parent-children relationship?

I am given a list of dictionaries like this:
[
{'A': ['B', 'C', 'D']},
{'B': ['E', 'F']},
{'C': ['E']},
{'F': ['G', 'H']}
]
A key in the dictionary is a parent of a corresponding dictionary value, i.e., {parent: [child1, child2, child3]}
How can I construct a tree-like dictionary in the following format like the following:
{'A':{'B':{'E': None,
'F': {'G': None,
'H': None}
},
'C': {'E': None}}
If a node doesn't have a child, we will fill its value with None. I don't know how to write a recursive process to transform the list into a dictionary, any idea?
Thanks!
You can do this with a recursive function:
def find_set(d, k, v):
for key, value in d.items():
if isinstance(value, dict):
find_set(d[key], k, v)
return
if key == k:
d[key] = {}
for i in v:
d[key][i] = None
return d
d[k] = {}
for i in v:
d[k][i] = None
return d
Code:
l = [{'A': ['B', 'C', 'D']}, {'B': ['E', 'F']}, {'C': ['E']}, {'F': ['G', 'H']}]
d = {}
for node in l:
for key, value in node.items():
find_set(d, key, value)
d will be :
{'A': {'B': {'E': None, 'F': {'G': None, 'H': None}, 'C': {'E': None}}, 'C': None, 'D': None}}
You can use recursion:
d = [{'A': ['B', 'C', 'D']}, {'B': ['E', 'F']}, {'C': ['E']}, {'F': ['G', 'H']}]
d1 = dict(list(i.items())[0] for i in d)
def flatten_structure(d, root = 'A'):
if root:
return {root:flatten_structure(d1[root], None)}
return {i:flatten_structure(d1[i], None) if i in d1 else None for i in d}
print(flatten_structure(d1['A']))
Output:
{'A': {'B': {'E': None, 'F': {'G': None, 'H': None}}, 'C': {'E': None}, 'D': None}}

Mapping values from for-loop lines to a list of tuples?

For the following code, I'm trying to print out the values within a list of tuples that are mapped from the line to it based on column headers. However, the mapping seems to go awry and do not give me the values I want.
import itertools as it
def buc(column_headers, tuples):
row_dict = {}
attribs = [1,2]
measure = 10
# generate binary table based on number of columns
binaries = [i for i in it.product(range(2), repeat=(len(attribs)))]
for line in binaries:
line = list(line)
# replace binary of 1 with 'ALL' or 0 with value from input attribs
for index, item in enumerate(line):
if (item == 1):
line[index] = 'ALL'
elif (item == 0):
line[index] = attribs[index]
line.append(measure)
print(line)
# map column values to column heading by index and store in row_dict (e.g. {'A': 1, 'B': 'ALL', 'M': 100} )
for i in range(len(line)):
row_dict[column_headers[i]] = line[i]
tuples.append(row_dict)
print(tuples)
The following is the current output I get:
>>> buc(['A', 'B', 'M'], [])
[1, 2, 10]
[1, 'ALL', 10]
['ALL', 2, 10]
['ALL', 'ALL', 10]
[{'A': 'ALL', 'B': 'ALL', 'M': 10}, {'A': 'ALL', 'B': 'ALL', 'M': 10}, {'A': 'ALL', 'B': 'ALL', 'M': 10}, {'A': 'ALL', 'B': 'ALL', 'M': 10}]
The correct output I want should be the following, where the lines is mapped to the tuples correctly, based on index of the column headings:
>>> buc(['A', 'B', 'M'], [])
[1, 2, 10]
[1, 'ALL', 10]
['ALL', 2, 10]
['ALL', 'ALL', 10]
[{'A': '1', 'B': '2', 'M': 10}, {'A': '1', 'B': 'ALL', 'M': 10}, {'A': 'ALL', 'B': '2', 'M': 10}, {'A': 'ALL', 'B': 'ALL', 'M': 10}]
Where have I done wrong?
This happens because your list tuples only contains a reference to the original dictionary. See this answer. You can fix this by copying the dictionary.
Replace
tuples.append(row_dict)
with
tuples.append(row_dict.copy())

how to append to a dictionary values from another dictionary if keys match

let's say I have two dictionaries
dict_1 ={'A': 'a', 'B':'b', 'C': 'c', 'D':'d', 'E':'e','F':f}
dict_2 ={'A': None, 'G': None, 'H': None, 'I': None,'L': None}
I'd like a function that returns the second dictionary as
dict_2 ={'A': 'a', 'G': None, 'H': None, 'I': None,'L': None}
which is matching the keys of dict_1 against those in dict_2. If one matches replace the value in dict_2 with the value in dict_1 for that key. Otherwise nothing.
A simple way to do this by iterating over dict_2's items and using dict_1.get() providing default value as dict_2 corresponding value -
>>> dict_1 ={'A': 'a', 'B':'b', 'C': 'c', 'D':'d', 'E':'e','F':f}
>>> dict_2 ={'A': None, 'G': None, 'H': None, 'I': None,'L': None}
>>> for k,v in dict_2.items():
... dict_2[k] = dict_1.get(k,v)
...
>>> dict_2
{'G': None, 'H': None, 'I': None, 'L': None, 'A': 'a'}
Same using dict comprehension -
>>> dict_1 ={'A': 'a', 'B':'b', 'C': 'c', 'D':'d', 'E':'e','F':f}
>>> dict_2 ={'A': None, 'G': None, 'H': None, 'I': None,'L': None}
>>> dict_2 = {k:dict_1.get(k,v) for k,v in dict_2.items()}
>>> dict_2
{'G': None, 'H': None, 'I': None, 'L': None, 'A': 'a'}
Another way is to find the common keys, and iterate over them like this:
dict_1 ={'A': 'a', 'B':'b', 'C': 'c', 'D':'d', 'E':'e','F':f}
dict_2 ={'A': None, 'G': None, 'H': None, 'I': None,'L': None}
for key in set(dict_1.iterkeys()) & set(dict_2.iterkeys()):
dict_2[key] = dict_1[key]
This should be much less computational expensive if it's relatively few common entries compared to the total number of entries in the dictionaries.
You could use dict comprehension and if else to do it :
dict_1 ={'A': 'a', 'B':'b', 'C': 'c', 'D':'d', 'E':'e','F':f}
dict_2 ={'A': None, 'G': None, 'H': None, 'I': None,'L': None}
dict_2={a : dict_1[a] if a in dict_1 else dict_2[a] for a in dict_2.keys() }
print dict_2
output:
{'A': 'a', 'H': None, 'I': None, 'L': None, 'G': None}
But this creates a new dict object
You can use dict.viewkeys to find the common keys:
dict_1 ={'A': 'a', 'B':'b', 'C': 'c', 'D':'d', 'E':'e','F':'f'}
dict_2 ={'A': None, 'G': None, 'H': None, 'I': None,'L': None}
for k in dict_1.viewkeys() & dict_2.viewkeys():
dict_2[k] = dict_1[k]
print(dict_2)
{'A': 'a', 'H': None, 'I': None, 'L': None, 'G': None}
For python3 just use .keys as it returns a dictionary-view-object not a list:
for k in dict_1.keys() & dict_2.keys():
dict_2[k] = dict_1[k]
print(dict_2)

Categories

Resources