Convert values from list of dictionaries from string to integer - python

I have a list of 54 dictionaries, formatted as so:
[{'1A': '1',
'3E': '2',
'PRODUCT NUMBER': '1',
'Week': '1'}
,
{'1A': '1',
'1B': '1',
'1C': '1',
'1D': '2',
'1E': '2',
'2C': '1',
'3E': '2',
'PRODUCT NUMBER': '2',
'Week': '1'},...] and etc
I am trying to convert the values from strings to integers.
I have successfully managed to do this for my very last dictionary, but it doesnt seem to be working for the rest.
This is my code:
for i in buyers: #buyers is the list
for n in buyers_dict: # the code works without this line the same, i cant figure out where to implement the 'n'
for k, v in buyers_list.items():
buyers_list[k] = int(v)
pprint.pprint(buyers)
Like I said, the 54th dictionary values are converted, but the rest are still strings
here is my excel file:
I've then condensed the dictionaries to just contain the key values pairs that have a value. Now I need to convert the values into integers.

Assuming your data is in this schema:
buyers = [{...}, {...}, ...]
You need to loop through the list of dicts then work on those dicts in particular:
for d in buyers:
for k, v in d.items():
d[k] = int(v)
Or in comprehension form:
buyers = [{k: int(v) for k, v in d.items()} for d in buyers]

d=[{'1A': '1',
'3E': '2',
'PRODUCT NUMBER': '1',
'Week': '1'}]
Using Comprehension
[{k:int(v)} for i in d for (k,v) in i.items() ]
Output:
[{'1A': 1}, {'3E': 2}, {'PRODUCT NUMBER': 1}, {'Week': 1}]

Related

Make a list consistent

I have 2 list ..
a = [{'Work': 'R'}, {'Area': 'S0'}, {'Type': 'PIV'}, {'Disc': 'LA'}, {'L': 'A'}]
b = [{'Key': '9', 'FileName': '123A.pdf', 'Code': '1', 'Type': 'PNHRG'}]
output -- [{'Key': '9', 'FileName': '123A.pdf', 'Code': '1', 'Type': 'PNHRG','Work': 'R','Area': 'S0','Type': 'PIV','Disc': 'LA','L': 'A'}]
I tried 'extend','append','insert' but did not get desired
output. tried all most all list operations with loops too. I am
not in position to change any kind of types for this.
Tried this solution too without luck. not sure where I am missing.
How do I make a flat list out of a list of lists?
You can use a doubly-nested dictionary comprehension, iterating over all the items in all the dicts in all the lists. Assuming multiple dicts in b might not be necessary, but makes it easier.
>>> a = [{'Work': 'R'}, {'Area': 'S0'}, {'Type': 'PIV'}, {'Disc': 'LA'}, {'L': 'A'}]
>>> b = [{'Key': '9', 'FileName': '123A.pdf', 'Code': '1', 'Type': 'PNHRG'}]
>>> [{k: v for lst in (a, b) for d in lst for k, v in d.items()}]
[{'Work': 'R', 'Area': 'S0', 'Type': 'PNHRG', 'Disc': 'LA', 'L': 'A', 'Key': '9', 'FileName': '123A.pdf', 'Code': '1'}]
Addendum: If there are any keys that appear in more than one dictionary, as is the case with "type" here, the value from the last dictionary that was iterated in the comprehension will be used, i.e. b here. If you need the value from a, do ... for lst in (b, a).... In your expected output, that key appears twice, but that is not possible unless you change the format, as in the other answer.
Extra from the answer provided by tobias_k:
If you want to combine both lists of dictionaries (and more when you have it) as a dictionary with a list of values in the same key. You can do this.
from collections import defaultdict
mydict = defaultdict(list)
for i in (a+b):
for key, value in i.items():
mydict[key].append(value)
mydict
Out[32]:
defaultdict(list,
{'Work': ['R'],
'Area': ['S0'],
'Type': ['PIV', 'PNHRG'],
'Disc': ['LA'],
'L': ['A'],
'Key': ['9'],
'FileName': ['123A.pdf'],
'Code': ['1']})

find matching string pattern in nested dict

I have a list of list where some can be empty, some contain one dict, and some has dicts where the key data has mixed type str, ints, dict.
[[],
[{'label': '0', 'data': {'text': ['pattern']}}],
[{'label': '0', 'data': {'text': ['pattern']}},
{'label': '1', 'data': 'a1s2'},
{'label': '9', 'data': 'adf21'},
{'label': '4', 'data': ''},
{'label': '6', 'data': '6250000000'},
{'label': '700', 'data': 2100000}]
]
How to filter and return the index of the list that matches a specific ['pattern'] ?
Expected output:
1, 2
Perhaps a list comprehension could work:
out = [i for i, li in enumerate(lst) for d in li if isinstance(d.get('data'), dict)
and d['data'].get('text') == ['pattern']]
Output:
[1, 2]
while one liners are really cool, I personally find them a bit harder to read, here a version with multiple lines
index = []
for i, li in enumerate(lst):
for d in li:
if type(d["data"]) == dict:
if d["data"]["text"][0] == "pattern":
print(d)
index.append(i)
print(index)

How can I remove a value in this list if it is not inside one of the keys of this nested dictionary?

Currently, I have the following weird nested dictionary:
d = {'start': {'0': {'start', 'near'}, '1': {'start'}}, 'near': {'1': {'end'}}, 'end': {}}
And the following list:
l = ['1', '0', '1', 'x', '0', '1']
If one of the values in l are not in one of the keys and values in the dictionary, remove it from the list.
So for example, in the list, there is an "x" and I am trying to see if there is anyway I can remove it with either l.remove() or if del / pop is better.
The thing that is giving me troubles is the dictionary.
What I have going so far:
d = {'start': {'0': {'start', 'near'}, '1': {'start'}}, 'near': {'1': {'end'}}, 'end': {}}
l = ['1', '0', '1', 'x', '0', '1']
for key, value in d.items():
for keys, values in value.items():
for number in l:
Get the set of keys:
keys = set.union(*[set(x.keys()) for x in d.values()])
#{'0', '1'}
Filter out the non-keys:
result = [item for item in l if item in keys]
#['1', '0', '1', '0', '1']

Multiplying the values of dictionaries with different keys

The problem of multiplying of values of two dictionaries with the same keys, I decided as follows:
v1={'name1': '10', 'name2': '20'}
v2={'name1': '4', 'name2': '5'}
foo = lambda dct_1, dct_2: {key: int(dct_2[key]) * int(dct_1[key]) for key in dct_2}
foo(v1, v2)
# Out: {'name1': 40, 'name2': 100}
How can I multiply values of two dictionaries in the same way, but with the different keys ?
v1={'name1': '10', 'name2': '20'}
v2={'quantity1': '4', 'quantity2': '5'}
#OUT: {'name1':'40', 'name2': '100'}
Assuming you always have corresponding nameX and quantityX values, you could use a simple replace on the keys:
foo = lambda dct_1, dct_2: {key: int(dct_2[key.replace('name', 'quantity')]) * int(dct_1[key]) for key in dct_1}
multiplydicts = lambda x,y: { key: str(int(v1[key]) * int(val)) for key,val in zip(v1.keys(), v2.values())}
Assuming that your dictionaries are the same size this should do the trick, and v2.values() will return the values of v2 in order of construction.
you can do :
>>> v1={'name1': '10', 'name2': '20'}
>>> v2={'quantity1': '4', 'quantity2': '5'}
>>> d={'name'+str(i+1) : int(v1['name'+str(i+1)])*int(v2['quantity'+str(i+1)]) for i in range(len(v1))}
>>> d
{'name2': 100, 'name1': 40}
You just need to add something to map the keys in the first dictionary to those in second. The easiest way to do it is with a third dictionary named keymap in the code below. The keys in the first dictionary determine the ones that will appear in the one returned.
This is needed because the order of keys in ordinary dictionaries is undefined, so you can't rely or predict what order they will appear in when you iterate over them.
v1={'name1': '10', 'name2': '20'}
v2={'quantity1': '4', 'quantity2': '5'}
keymap = {'name1': 'quantity1', 'name2': 'quantity2'} # Added.
foo = (lambda dct_1, dct_2:
{key: int(dct_2[keymap[key]]) * int(dct_1[key]) for key in dct_1})
print(foo(v1, v2)) # -> {'name1': 40, 'name2': 100}

merge to dictionaries preserving different values

I am very new to python (python 3.2) and I have been struggling with a difficult problem. I have two dictionary with listed lists:
d1 = {
'mammals': ['dog', '5', 'cat', '4', 'mouse', '4', 'bat', '3'],
'bird': ['robin', '8', 'bluejay', '6', 'goose', '5', 'cardinal', '5']
}
and
d2 = {
'mammals': ['cow', '5', 'horse', '4', 'cat', '4', 'dog', '3', 'beaver', '3'],
'bird': ['bluejay', '9', 'goose', '8', 'eagle', '8', 'robin', '7', 'duck', '6', 'cardinal', '5']
}
In each dictionary, the pair name-number (for instance, 'dog', '5') correspond to how many instances of said item where present in the original data bases.
What I need is to merge the two dictionaries in a way that information about quantity preserved (again, in the example, the new dictionary would have 'dog', '5', '3'. So that the merged dictionary would look somewhat like (I am not necessarily committed to nested dictionaries. I wrote it this way for easiness of visualization. The important thing is too keep the information):
d_merged = {
'mammals': [{'dog': ['5', '3']}, {'cat': ['4', '4']}, {'mouse': '4'}, {'bat': '3'} , {'cow': '5'},
{'horse': '4'}, {'beaver': '3'}],
'bird': [{'robin': ['8', '7']}, {'bluejay': ['6', '9']}, {'goose': ['5','8']}, {'cardinal': ['5',
'5']}, {'eagle': '8'}, {'duck', '6'}]
}
I have tried various things with tuples, nested dictionaries and other possibilities, but the result has been a mess. It would mean a lot if someone could point me in a good direction to solve this. I thank you very much
The most readable way to do it is probably as follows:
output = {}
for key in d1.keys():
output[key] = {}
lst = d1[key]
for name, count in (lst[i:i+2] for i in range(0, len(lst), 2)):
output[key][name] = (int(count),)
for key in d2.keys():
if key not in output:
output[key] = {}
lst = d2[key]
for name, count in (lst[i:i+2] for i in range(0, len(lst), 2)):
if name in output[key].keys():
output[key][name] += (int(count),)
else:
output[key][name] = (int(count),)
In incomprehensible dictionary comprehensions, you can do it in two steps
d = {k: {a: int(b) for a, b in (v[i:i+2] for i in range(0, len(v), 2))}
for k, v in d.items()}
To turn them into dictionaries of dictionaries, e.g.
{'mammals': {'cat': 4, 'cow': 5, 'dog': 3, 'beaver': 3, 'horse': 4},
'bird': {'goose': 8, 'duck': 6, 'eagle': 8, 'bluejay': 9, 'robin': 7, 'cardinal': 5}}
Then
output = {k1: {k2: (d1.get(k1, {}).get(k2), d2.get(k1, {}).get(k2))
for k2 in set(list(d1.get(k1, {}).keys()) + list(d2.get(k1, {}).keys()))}
for k1 in set(list(d1.keys()) + list(d2.keys()))}
To combine the two.
Note that these methods both work even if there are different keys at the two levels (e.g. adding d1['reptiles'] = {'lizard': 10}).
first you can change d1 and d2 to be dictionaries that is easier to work with:
[note that list[::2] is sublist that holds all the item in the even indices, and list[1::2] holds the odds.]
>>> dc1 = {}
>>> for family in d1.keys():
l = d1[family]
dc1[family] = {l[::2][family]:[l[1::2][family]] for family in range(len(l)/2)}
>>> dc2 = {}
>>> for family in d1.keys():
l = d2[family]
dc2[family] = {l[::2][family]:[l[1::2][family]] for family in range(len(l)/2)}
now dc1 and dc2 are these:
>>> dc1
{'mammals': {'bat': ['3'], 'mouse': ['4'], 'dog': ['5'], 'cat': ['4']},
'bird': {'goose': ['5'], 'cardinal': ['5'], 'robin': ['8'], 'bluejay': ['6']}}
>>> dc2
{'mammals': {'beaver': ['3'], 'horse': ['4'], 'dog': ['3'], 'cow': ['5'], 'cat': ['4']},
'bird': {'eagle': ['8'], 'bluejay': ['9'], 'goose': ['8'], 'cardinal': ['5'], 'duck': ['6'], 'robin': ['7']}}
and then you just need to combine them
>>> d_merged = {}
>>> families = set(d1.keys()+d2.keys())
>>> family2animals = {family:list(set(dc1[family].keys()+dc2[family].keys())) for family in families}
>>> for family in families:
d_merged[family] = [{animal:dc1[family].get(animal,[])+dc2[family].get(animal,[])} for animal in family2animals[family]]

Categories

Resources