Converting a dictionary to a mathematical expression - python

{'YOU': {'HE': {'EST': 8, 'OLM': 6}, 'SLO': {'WLR': 8}},
'ARE': {'KLP': {'EST': 6}, 'POL': {'WLR': 4}},
'DOING': {'TIS': {'OIL': 8}},
'GREAT': {'POL': {'EOL': 6}},
'WORK': {'KOE': {'RIW': 8, 'PNG': 4}, 'ROE': {'ERC': 8, 'WQD': 6}},
'KEEP': {'PAR': {'KOM': 8, 'RTW': 6}, 'PIL': {'XCE': 4, 'ACE': 8}},
'ROCKING': {'OUL': {'AZS': 6, 'RVX': 8}}}
Need to perform a calculation on the numbers in dictionary.
Eg: {'YOU': {'HE': {'EST': 8, 'OLM': 6}, 'SLO': {'WLR': 8}},
'WORK': {'KOE': {'RIW': 8, 'PNG': 4}, 'ROE': {'ERC': 8, 'WQD': 6}}} for this example the output would be
[(8+6)x8]+[(8+4)x(8+6)]
[14x8]+[12x14]
112+168
280
Following is the code I tried :
a = [tuple([k]+list(v.keys())+list(j.values())) for k,v in data.items() for i,j in v.items()]
and it gives :
[('YOU', 'HE', 'SLO', 8, 6),
('YOU', 'HE', 'SLO', 8),
('ARE', 'KLP', 'POL', 6),
('ARE', 'KLP', 'POL', 4),
('DOING', 'TIS', 8),
('GREAT', 'POL', 6),
('WORK', 'KOE', 'ROE', 8, 4),
('WORK', 'KOE', 'ROE', 8, 6),
('KEEP', 'PAR', 'PIL', 8, 6),
('KEEP', 'PAR', 'PIL', 4, 8),
('ROCKING', 'OUL', 6, 8)]

The rules aren't well-defined, but I'll give it a shot anyway. I am assuming you only want this calculation to apply to keys YOU and WORK in your nested dictionary. I think a list comprehension will get pretty complicated, and it's more readable to work with loops.
For each key YOU and WORK, I summed up these two innermost sets of values 8+6, 8 for YOU and 8+4, 8+6 for WORK, multiplied these values together 14*8 for YOU and 12*14 for WORK, then added the products together to get the result = 280
dict_nested = {'YOU': {'HE': {'EST': 8, 'OLM': 6}, 'SLO': {'WLR': 8}},
'ARE': {'KLP': {'EST': 6}, 'POL': {'WLR': 4}},
'DOING': {'TIS': {'OIL': 8}},
'GREAT': {'POL': {'EOL': 6}},
'WORK': {'KOE': {'RIW': 8, 'PNG': 4}, 'ROE': {'ERC': 8, 'WQD': 6}},
'KEEP': {'PAR': {'KOM': 8, 'RTW': 6}, 'PIL': {'XCE': 4, 'ACE': 8}},
'ROCKING': {'OUL': {'AZS': 6, 'RVX': 8}}}
keys = ['YOU','WORK']
result = 0
for key in keys:
inner_keys = dict_nested[key].keys()
# multiply the values together for the first values of the inner key
inner_product = 1
for inner_key in inner_keys:
inner_product *= sum(list(dict_nested[key][inner_key].values()))
# print(inner_product)
result += inner_product
Output:
>>> result
280

NOTE
By any means don't use eval, it is insecure ("eval is evil").
For more details about eval harmfulness (there are too many, I've just cherry-picked one) read here.
Some Inspiration Towards a Solution
As others and smarter before me have noted, I haven't found any reasonable explanation regarding the operands assignment in the example you've provided.
However, this is a little try - hope it will help you with the challenge.
So here you go:
import json
d = {'YOU': {'HE': {'EST': 8, 'OLM': 6}, 'SLO': {'WLR': 8}}, 'WORK': {'KOE': {'RIW': 8, 'PNG': 4}, 'ROE': {'ERC': 8, 'WQD': 6}}}
# Convet dictionary to a string
r = json.dumps(d)
# Convert string to char list
chars = list(r)
# Legal chars needed for computing
legal_chars = ['{', '}', ','] + [str(d) for d in range(10)]
# Filtering in only legal chars
filtered_chars = [x for x in chars if x in legal_chars]
# Replacing the {} with () and , with +
expression = ''.join(filtered_chars).replace('{', '(').replace('}', ')').replace(',', '+')
# Evaluating expression
result = eval(expression)
# (((8+6)+(12))+((8+4)+(8+6)))=52
print(f'{expression}={result}')

Related

Check if dict key is a substring of any other element in the dictionary in Python?

I've got a dictionary ngram_list as follows:
ngram_list = dict_items([
('back to back breeding', {'wordcount': 4, 'count': 3}),
('back breeding', {'wordcount': 2, 'count': 5}),
('several consecutive heats', {'wordcount': 3, 'count': 2}),
('how often should', {'wordcount': 3, 'count': 2}),
('often when breeding', {'wordcount': 3, 'count': 1})
])
I want to sort the list from the shortest wordcount to the largest and then loop through the dictionary and if the key is a substring of any other item, delete it (the substring item.)
Expected output:
ngram_list = dict_items([
('several consecutive heats', {'wordcount': 3, 'count': 2}),
('how often should', {'wordcount': 3, 'count': 2}),
('often when breeding', {'wordcount': 3, 'count': 1}),
('back to back breeding', {'wordcount': 4, 'count': 3})
])
First filter the input dict to get rid of unwanted items, then using sorted function with key to sort the items by wordcount, and finally build the dict with OrderedDict
Using simple in to check for substring only, might need to use regex if wanna take care exact full word boundary match
from collections import OrderedDict
ngram_dict = {
'back to back breeding': {'wordcount': 4, 'count': 3},
'back breeding': {'wordcount': 2, 'count': 5},
'several consecutive heats': {'wordcount': 3, 'count': 2},
'how often should': {'wordcount': 3, 'count': 2},
'often when breeding': {'wordcount': 3, 'count': 1}
}
# ngram items with unwanted items filter out
ngram_filter = [i for i in ngram_dict.items() if not any(i[0] in k and i[0] != k for k in ngram_dict.keys())]
final_dict = OrderedDict( sorted(ngram_filter, key=lambda x:x[1].get('wordcount')) )
# final_dict = OrderedDict([('several consecutive heats', {'count': 2, 'wordcount': 3}), ('how often should', {'count': 2, 'wordcount': 3}), ('often when breeding', {'count': 1, 'wordcount': 3}), ('back to back breeding', {'count': 3, 'wordcount': 4})])
All this can be fitted into 1 liner as below
from collections import OrderedDict
final_dict = OrderedDict(
sorted((i for i in ngram_dict.items() if not any(i[0] in k and i[0] != k for k in ngram_dict.keys())),
key=lambda x:x[1].get('wordcount')) )

create nested dictionarys in python3

I would like to create nested dict in python3, I've the following list(from a sql-query):
[('madonna', 'Portland', 'Oregon', '0.70', '+5551234', 'music', datetime.date(2016, 9, 8), datetime.date(2016, 9, 1)), ('jackson', 'Laredo', 'Texas', '2.03', '+555345', 'none', datetime.date(2016, 5, 23), datetime.date(2016, 5, 16)), ('bohlen', 'P', 'P', '2.27', '+555987', 'PhD Student', datetime.date(2016, 9, 7))]
I would like to have the following output:
{madonna:{city:Portland, State:Oregon, Index: 0.70, Phone:+5551234, art:music, exp-date:2016, 9, 8, arrival-date:datetime.date(2016, 5, 23)},jackson:{city: Laredo, State:Texas........etc...}}
Can somebody show me an easy to understand code?
I try:
from collections import defaultdict
usercheck = defaultdict(list)
for accname, div_ort, standort, raum, telefon, position, exp, dep in cur.fetchall():
usercheck(accname).append[..]
but this don't work, I can't think any further myself
You can use Dict Comprehension (defined here) to dynamically create a dictionary based on the elements of a list:
sql_list = [
('madonna', 'Portland', 'Oregon', '0.70', '+5551234', 'music', datetime.date(2016, 9, 8), datetime.date(2016, 9, 1)),
('jackson', 'Laredo', 'Texas', '2.03', '+555345', 'none', datetime.date(2016, 5, 23), datetime.date(2016, 5, 16)),
('bohlen', 'P', 'P', '2.27', '+555987', 'PhD Student', datetime.date(2016, 9, 7))
]
sql_dict = {
element[0]: {
'city': element[1],
'state': element[2],
'index': element[3],
'phone': element[4],
'art': element[5],
} for element in sql_list
}
Keep in mind that every item in the dictionary needs to have a key and a value, and in your example you have a few values with no key.
If you have a list of the columns, you can use the zip function:
from collections import defaultdict
import datetime
# list of columns returned from your database query
columns = ["city", "state", "index", "phone", "art", "exp-date", "arrival-date"]
usercheck = defaultdict(list)
for row in cur.fetchall():
usercheck[row[0]] = defaultdict(list, zip(columns, row[1:]))
print usercheck
This will output a dictionary like:
defaultdict(<type 'list'>, {'madonna': defaultdict(<type 'list'>, {'city': 'Portland', 'art': 'music', 'index': '0.70', 'phone': '+5551234', 'state': 'Oregon', 'arrival-date': datetime.date(2016, 9, 1), 'exp-date': datetime.date(2016, 9, 8)}), 'jackson': defaultdict(<type 'list'>, {'city': 'Laredo', 'art': 'none', 'index': '2.03', 'phone': '+555345', 'state': 'Texas', 'arrival-date': datetime.date(2016, 5, 16), 'exp-date': datetime.date(2016, 5, 23)}), 'bohlen': defaultdict(<type 'list'>, {'city': 'P', 'art': 'PhD Student', 'index': '2.27', 'phone': '+555987', 'state': 'P', 'arrival-date': None, 'exp-date': datetime.date(2016, 9, 7)})})
When using defaultdict, the argument specifies the default value type in the dictionary.
from collections import defaultdict
usercheck = defaultdict(dict)
for accname, div_ort, standort, raum, telefon, position, exp, dep in cur.fetchall():
usercheck[accname]['city'] = div_ort
usercheck[accname]['state'] = standout
...
The keys in the dictionary are referenced using [key], not (key).

Pythonic sort a list of dictionaries in a tricky order

I have a list of id's sorted in a proper oder:
ids = [1, 2, 4, 6, 5, 0, 3]
I also have a list of dictionaries, sorted in some random way:
rez = [{'val': 7, 'id': 1}, {'val': 8, 'id': 2}, {'val': 2, 'id': 3}, {'val': 0, 'id': 4}, {'val': -1, 'id': 5}, {'val': -4, 'id': 6}, {'val': 9, 'id': 0}]
My intention is to sort rez list in a way that corresponds to ids:
rez = [{'val': 7, 'id': 1}, {'val': 8, 'id': 2}, {'val': 0, 'id': 4}, {'val': -4, 'id': 6}, {'val': -1, 'id': 5}, {'val': 9, 'id': 0}, {'val': 2, 'id': 3}]
I tried:
rez.sort(key = lambda x: ids.index(x['id']))
However that way is too slow for me, as len(ids) > 150K, and each dict actually had a lot of keys (some values there are strings). Any suggestion how to do it in the most pythonic, but still fastest way?
You don't need to sort because ids specifies the entire ordering of the result. You just need to pick the correct elements by their ids:
rez_dict = {d['id']:d for d in rez}
rez_ordered = [rez_dict[id] for id in ids]
Which gives:
>>> rez_ordered
[{'id': 1, 'val': 7}, {'id': 2, 'val': 8}, {'id': 4, 'val': 0}, {'id': 6, 'val': -4}, {'id': 5, 'val': -1}, {'id': 0, 'val': 9}, {'id': 3, 'val': 2}]
This should be faster than sorting because it can be done in linear time on average, while sort is O(nlogn).
Note that this assumes that there will be one entry per id, as in your example.
I think you are on the right track. If you need to speed it up, because your list is too long and you are having quadratic complexity, you can turn the list into a dictionary first, mapping the ids to their respective indices.
indices = {id_: pos for pos, id_ in enumerate(ids)}
rez.sort(key = lambda x: indices[x['id']])
This way, indices is {0: 5, 1: 0, 2: 1, 3: 6, 4: 2, 5: 4, 6: 3}, and rez is
[{'id': 1, 'val': 7},
{'id': 2, 'val': 8},
{'id': 4, 'val': 0},
{'id': 6, 'val': -4},
{'id': 5, 'val': -1},
{'id': 0, 'val': 9},
{'id': 3, 'val': 2}]

How can I change from nested dictionaries to a flat array?

I want to change this in python
Before :
{'NewYork': {'Paris': 12, 'Hawaii': 8, 'Tokyo': 11, 'Incheon': 12, 'LA': 2},
'Beijing': {'Hongkong': 3, 'Cebu': 5},
'Incheon': {'Cairo': 10, 'LA': 11, 'Tokyo': 1},
'Tokyo': {'NewYork': 12, 'Paris': 14, 'LA': 9}}
After :
[("NewYork","Paris",12),
("NewYork","Hawaii",8),
("Newyork","Tokyo",11),
("NewYork","Incheon",12),
("NewYork","LA",2),
("Beijing","HongKong",3),
("Beijing","Cebu",5),
("Incheon","Cairo",10),
("Incheon","LA",11),
("Incheon","Tokyo",1),
("Tokyo","NewYork",12),
("Tokyo","Paris",14),
("Tokyo","LA",9)]
How can I do this?
>>> before = {'NewYork': {'Paris': 12, 'Hawaii': 8, 'Tokyo': 11, 'Incheon': 12, 'LA': 2},
... 'Beijing': {'Hongkong': 3, 'Cebu': 5}, 'Incheon': {'Cairo': 10, 'LA': 11, 'Tokyo': 1},
... 'Tokyo': {'NewYork': 12, 'Paris': 14, 'LA': 9}}
>>>
>>> print [(key,k,v) for key,val in before.iteritems() for k,v in val.iteritems()]
[('NewYork', 'Paris', 12), ('NewYork', 'LA', 2), ('NewYork', 'Hawaii', 8), ('NewYork', 'Incheon', 12), ('NewYork', 'Tokyo', 11), ('Beijing', 'Hongkong', 3), ('Beijin
g', 'Cebu', 5), ('Incheon', 'Cairo', 10), ('Incheon', 'Tokyo', 1), ('Incheon', 'LA', 11), ('Tokyo', 'NewYork', 12), ('Tokyo', 'Paris', 14), ('Tokyo', 'LA', 9)]
You can create an array with a list comprehension and two lots of iteration:
>>> city_pairings = {'NewYork': {'Paris': 12,
... 'Hawaii': 8,
... 'Tokyo': 11,
... 'Incheon': 12,
... 'LA': 2},
... 'Beijing': {'Hongkong': 3,
... 'Cebu': 5},
... 'Incheon': {'Cairo': 10,
... 'LA': 11,
... 'Tokyo': 1},
... 'Tokyo': {'NewYork': 12,
... 'Paris': 14,
... 'LA': 9}}
>>> flat = [(city, other_city, value)
... for city, pairings in city_pairings.iteritems()
... for other_city, value in pairings.iteritems()]
>>> from pprint import pprint
>>> pprint(flat)
[('NewYork', 'Paris', 12),
('NewYork', 'LA', 2),
('NewYork', 'Hawaii', 8),
('NewYork', 'Incheon', 12),
('NewYork', 'Tokyo', 11),
('Beijing', 'Hongkong', 3),
('Beijing', 'Cebu', 5),
('Incheon', 'Cairo', 10),
('Incheon', 'Tokyo', 1),
('Incheon', 'LA', 11),
('Tokyo', 'NewYork', 12),
('Tokyo', 'Paris', 14),
('Tokyo', 'LA', 9)]
The second cities aren't exactly in the order you wanted as the dictionary sorts them according to some scheme. To have cities in the order they were inserted into the dictionary you'll have to do something else, using OrderedDict, for example.
This will do the trick:
dict.items()

python: iterate through list and replace elements with corresponding dictionary values

I am trying to replace list element value with value looked up in dictionary how do I do that?
list = [1, 3, 2, 10]
d = {'id': 1, 'val': 30},{'id': 2, 'val': 53}, {'id': 3, 'val': 1}, {'id': 4, 'val': 9}, {'id': 5, 'val': 2}, {'id': 6, 'val': 6}, {'id': 7, 'val': 11}, {'id': 8, 'val': 89}, {'id': 9, 'val': 2}, {'id': 10, 'val': 4}
for i in list:
for key, v in d.iteritems():
???
???
so at the end I am expecting:
list = [30, 1, 53, 4]
thank you
D2 = dict((x['id'], x['val']) for x in D)
L2 = [D2[x] for x in L]
td = (
{'val': 30, 'id': 1},
{'val': 53, 'id': 2},
{'val': 1, 'id': 3},
{'val': 9, 'id': 4},
{'val': 2, 'id': 5},
{'val': 6, 'id': 6},
{'val': 11, 'id': 7},
{'val': 89, 'id': 8},
{'val': 2, 'id': 9},
{'val': 4, 'id': 10}
)
source_list = [1, 3, 2, 10]
final_list = []
for item in source_list:
for d in td:
if d['id'] == item:
final_list.append(d['val'])
print('Source : ', source_list)
print('Final : ', final_list)
Result
Source : [1, 3, 2, 10]
Final : [30, 1, 53, 4]

Categories

Resources