extract data from file as a dictonary - python

could you please advice how to read data from file as a dict.
file contains the following lines:
{'foo1': (0, 10), 'foo2': (0, 9), 'foo3': (0, 20)}
{'foo4': (0, 16), 'foo5': (0, 7), 'foo6': (0, 13), 'foo7': (0, 11)}
{'foo8': (0, 8), 'foo9': (0, 8), 'foo10': (0, 7)}
{'foo11': (0, 8)}
all data in {'key': (value, value)} format. All keys in the file are different.
I'd like to get the following "dict":
{'foo1': (0, 1), 'foo2': (0, 0), 'foo3': (0, 1), 'foo4': (1, 0), 'foo5': (0, 0), 'foo6': (0, 5), 'foo7': (0, 2), 'foo8': (2, 2), 'foo9': (1, 1), 'foo10': (0, 7), 'foo11': (0, 1)}
is it possible to extract dicts from the file as merged dict?
For a moment I get only "list" from the file and stucked at this step
import ast
with open('filename') as f:
content = [ ast.literal_eval( l ) for l in f.readlines() ]
print(content)
Output:
[{'foo1': (0, 10), 'foo2': (0, 9), 'foo3': (0, 20)}, {'foo4': (0, 16), 'foo5': (0, 7), 'foo6': (0, 13), 'foo7': (0, 11)}, {'foo8': (0, 8), 'foo9': (0, 8), 'foo10': (0, 7)}, {'foo11': (0, 8)}]

Check out ast.literal_eval(): https://www.kite.com/python/answers/how-to-read-a-dictionary-from-a-file-in--python

If you are totally confident in this file being innocent and only a dictionary, then you can use the python built-in function eval to get the job done. e.g.:
myfile = open("file.txt", "r")
mydict = eval(myfile.read())
If this allows any user input into the file, however, this could be used to potentially run arbitrary code on your machine. There are precautions to be took if this is reliant on user input, see the top answer on Python: make eval safe for some ideas.

As you get a list of dictionary in content due to list comprehension.
I will modify a little.
import ast
content = {}
with open('filename') as f:
content = content.update(content,ast.literal_eval( l ) for l in f.readlines())
print(content)
See if it works I am beginner. I learned how to merge dictionary from below link.
https://levelup.gitconnected.com/7-different-ways-to-merge-dictionaries-in-python-30148bf27add

Related

Repeat elememts based on another elements in the nested list

I have a nested list e.g., ls=[((0,3),(1,0),(2,2),(3,0)),((0,0),(1,3),(2,2),(3,0))].
And I would like to have the following modified list:
modified_ls=[((0,0),(0,0),(0,0),(1,0),(2,0),(2,0),(3,0)),((0,0),(1,0),(1,0),(1,0),(2,0),(2,0),(3,0))]
There the element (x,0) in modified_ls is repeated by N (N!=0) times which is based on the element (x, N) in ls.
Here is what I do (quite stupid):
ls=[((0,3),(1,0),(2,2),(3,0)),((0,0),(1,3),(2,2),(3,0))]
modified_temp_ls=[]
for ii in ls:
for jj in ii:
temp=jj[1]
if temp==0:
modified_temp_ls.append(jj)
else:
while temp:
modified_temp_ls.append((jj[0],0))
temp-=1
ls2=modified_temp_ls[0:int(len(modified_temp_ls)/2)]
ls3=modified_temp_ls[int(len(modified_temp_ls)/2):int(len(modified_temp_ls))]
modified_ls=[]
modified_ls.append(tuple(ls2))
modified_ls.append(tuple(ls3))
Are there any simple way to do it (e.g, without using ls2 and ls3, etc.)? Thank you very much in advance for any suggestions!
This is just list manipulation. Generate the individual sequences, then use sum to combine them into a single list.
ls=[((0,3),(1,0),(2,2),(3,0)),((0,0),(1,3),(2,2),(3,0))]
accum = []
for k in ls:
accum.append(sum([ [(i,0)]*max(1,n) for i,n in k ],[]))
print(accum)
Output:
[[(0, 0), (0, 0), (0, 0), (1, 0), (2, 0), (2, 0), (3, 0)], [(0, 0), (1, 0), (1, 0), (1, 0), (2, 0), (2, 0), (3, 0)]]
Or for the obligatory one liner:
ls=[((0,3),(1,0),(2,2),(3,0)),((0,0),(1,3),(2,2),(3,0))]
accum = [sum([[(i,0)]*max(1,n) for i,n in k ],[]) for k in ls]

Converting keys from float to int in dict in dict in list in dict

I've a dict data as below. I want to convert the float into integers. How do I go about it? I tried a few ways but to no avail.
data:
data =
{'ABC': {'2020-09-01': [{487.0: (0, 1), 488.0: (1, 2)}, {489.0: (0, 1), 481.0: (1, 2)}]},
'CDE': {'2020-01-01': [{484.0: (0, 1), 483.0: (1, 2)}, {482.0: (0, 1), 481.0: (1, 2)}]}}
I want this:
{'ABC': {'2020-09-01': [{487: (0, 1), 488: (1, 2)}, {489: (0, 1), 481: (1, 2)}]},
'CDE': {'2020-01-01': [{484: (0, 1), 483: (1, 2)}, {482: (0, 1), 481: (1, 2)}]}}
I tried this code, but I get this error "RuntimeError: dictionary keys changed during iteration":
I understand keys are immutable so I googled and found "pop" is an alternative solution
for i in data:
for date in data[i]:
for model in range(0, len(data[i][date])):
for k, v in data[i][date][model].items():
data[i][date][model][int(k)] = data[i][date][model].pop(k)
The problem is that you are tying to modify the dictionary while iterating over the same in:
for k, v in data[i][date][model].items():
data[i][date][model][int(k)] = data[i][date][model].pop(k)
You could consider using list comprehension instead:
for k_l1, v_l1 in data.items(): #iterate first level of dict
for k_l2, v_l2 in v_l1.items(): #iterate second level of dict
data[k_l1][k_l2] = [{ int(key): val for key, val in elt.items() } for elt in v_l2] # update the list
Output:
{'ABC': {'2020-09-01': [{487: (0, 1), 488: (1, 2)}, {489: (0, 1), 481: (1, 2)}]}, 'CDE': {'2020-01-01': [{484: (0, 1), 483: (1, 2)}, {482: (0, 1), 481: (1, 2)}]}}

How to add N OrderDict() in python

Assuming that I have 2 OrderedDict(), I can get the result of the (+) operation by doing the following action:
dict1 = OrderedDict([(52, 0),
(53, 0),
(1, 0),
(2, 0),
(3, 0),
(4, 0),
(5, 0),
(6, 0),
(7, 0),
(8, 0),
(9, 0),
(10, 0),
(11, 1)])
dict2 = OrderedDict([(52, 0),
(53, 0),
(1, 0),
(2, 5),
(3, 0),
(4, 0),
(5, 0),
(6, 1),
(7, 0),
(8, 0),
(9, 0),
(10, 1),
(11, 1)])
dict3 = OrderedDict((k, dict1[k] + dict2[k]) for k in dict1 if k in dict2)
print(dict3)
OrderedDict([(52, 0),
(53, 0),
(1, 0),
(2, 5),
(3, 0),
(4, 0),
(5, 0),
(6, 1),
(7, 0),
(8, 0),
(9, 0),
(10, 1),
(11, 2)])
My question is: how can I generalize the above action so I can get the (+) operation result for N OrderedDict()?
By testing each key for membership of each other dict you're essentially performing an operation of a set intersection, but you can't actually use set intersections because sets are unordered in Python.
You can work around this limitation by installing the ordered-set package, so that you can use the OrderedSet.intersection method to obtain common keys among the dicts ordered by keys in the first dict, which you can then iterate over to construct a new OrderedDict with each value being the sum of the values of the current key from all dicts:
from ordered_set import OrderedSet
dicts = [dict1, dict2]
common_keys = OrderedSet.intersection(*dicts)
print(OrderedDict((k, sum(d[k] for d in dicts)) for k in common_keys))
Demo: https://replit.com/#blhsing/FlawlessGrowlingAccounting
Some naive approach using map-reduce. Note that I didn't test the following code, so it might need some adjustments
import operator
dicts = [dict1, dict2, dict3, dict4]
dicts_keys = map(lambda d: set(d.keys()), dicts)
common_keys = set.intersection(*dicts_keys)
sum_dict = OrderedDict(
(k, reduce(operator.add, map(lambda d: d[k], dicts)))
for k in common_keys)
In case you don't want to install an external package, a similar result can be achieved by using this function:
def add_dicts(*args):
items_list = list()
for k in args[0]:
if all([k in arg for arg in args[1:]]):
value = 0
for arg in args:
value += arg[k]
items_list.append((k, value))
return OrderedDict(items_list)
To call it:
dict3 = add_dicts(dict1, dict2)
dict4 = add_dicts(dict1, dict2, dict3)
If you want to call it with a list of dictionaries:
dict_list=[dict1, dict2]
dict5 = add_dicts(*dict_list)
More information about *args can be found in this answer

Number of passengers. Error: list indices must be integers or slices, not list

So, I'm trying to sum the number of passenger at each stop.
The "stops" variable are the number of stops, and is conformed by a tuple which contains the in's and out's of passengers, example:
stops = [(in1, out1), (in2, out2), (in3, out3), (in4, out4)]
stops = [(10, 0), (4, 1), (3, 5), (3, 4), (5, 1), (1, 5), (5, 8), (4, 6), (2, 3)]
number_passenger_per_stop = []
for i in stops:
resta = stops[i][0] - stops[i][1]
number_passenger_per_stop.append(resta)
print(number_passenger_per_stop)
I can do the math like this outside the loop, but I don't understand why in the loop crashes:
stops[i][0] - stops[i][1]
i is not the list index, it's the list element itself. You don't need to write stops[i].
resta = i[0] - i[1]
Your code would be correct if you had written
for i in range(len(stops)):
You could also replace the entire thing with a list comprehension:
number_passenger_per_stop = [on - off for on, off in stops]
I just edited the for loop to adress each in the index in the list correctly, you needed to call each element in the list by its position, and not by its value:
stops = [(10, 0), (4, 1), (3, 5), (3, 4), (5, 1), (1, 5), (5, 8), (4, 6), (2, 3)]
number_passenger_per_stop = []
for i in range(len(stops)):
resta = stops[i][0] - stops[i][1]
number_passenger_per_stop.append(resta)
print(number_passenger_per_stop)
Output:
[10, 3, -2, -1, 4, -4, -3, -2, -1]

How to put the tuple (i,j) in a list multiple times without using concatenation?

I want to add some tuples (i,j) in a list as many time as they occur in another function. My result right now is [[(0, 0), (0, 0)]], but I want it to be only a single list [(0, 0), (0, 0)]. Is there any way I can do this without using libraries?
list= [[(i,j)]*number_occurences]
print(list)
>>> [[(0, 0), (0, 0)]]
You literally wrote the [[ that you don't want. So, simply don't do that! Write just the one [ instead.
For example:
>>> [(1,2)]*5
[(1, 2), (1, 2), (1, 2), (1, 2), (1, 2)]

Categories

Resources