find matching string pattern in nested dict - python

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)

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']})

Convert values from list of dictionaries from string to integer

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}]

Modify list item based on key:value match python

Let's say we have the following list:
my_list = [{'id': '1', 'status':'new'},
{'id': '2', 'status':'closed'},
{'id': '3', 'status':'new'}]
Is there a way to change the 'status' of the dict with 'id':'1'?
This way the list will result in:
my_list = [{'id': '1', 'status':'changed'}, # <---
{'id': '2', 'status':'closed'},
{'id': '3', 'status':'new'}]
I see that one approach could be something like:
for i in range(len(my_list)):
if my_list[i]['id'] == 'desired_id':
my_list[i]['status'] = 'desired_status'
break
Is this the only option or is there a "nicer" approach?
Unless you have an option to change your data's structure (a dict of dicts for example instead of list of dicts), then no - since it's a list, you'll have to loop over it to find the dict with the matching id. So, if you're confined to using a list, the only thing to change is to loop on items instead of indices:
for d in my_list:
if d['id'] == 'desired_id':
d['status'] = 'desired_status'
break
else:
print("There is no ID matching the desired search")
But, if you can change your data to be, for example:
my_dict = {'1': {'status': 'new'},
'2': {'status': 'closed'},
'3': {'status': 'new'}}
...then there is no need for loops at all (that is assuming that ids can't repeat):
try:
my_dict['desired_id']['status'] = 'desired_status'
except KeyError:
print("There is no ID matching the desired search")
Since this a list of dict. looping through it would be the way that strikes my mind :
my_list = [{'id': '1', 'status':'new'},{'id': '2', 'status':'closed'},{'id': '3', 'status':'new'}]
for i,j in enumerate(my_list):
if j['id'] == '1':
my_list[i]['status']='changed'
print(my_list)

Map multiple lists(acting as values) with a single list(acting as key) to create a dictionary in python

headers = ['id', 'product', 'plan']
values = [['1', 'abc', '123'],['2', 'efg', '1234'],['3', 'ijk', '890']]
data = []
for entries in values:
data.append(dict(itertools.izip(headers, entries)))
The common pattern for this type of data abstraction is a list of dicts which easily translates to JSON - an array of objects.
import pprint
headers = ['id', 'product', 'plan']
values = [
['1', 'abc', '123'],
['2', 'efg', '1234'],
['3', 'ijk', '890'],
]
list_of_dicts = [dict(zip(headers, row)) for row in values]
pprint.pprint(list_of_dicts)
output
[{'id': '1', 'plan': '123', 'product': 'abc'},
{'id': '2', 'plan': '1234', 'product': 'efg'},
{'id': '3', 'plan': '890', 'product': 'ijk'}]

How to delete characters from string values of dictionaries in list?

litofdict = [{'name': 'Mike', 'surname':'Mikeson', 'age':'15\n'},{'name': 'John', 'surname':'Johnson', 'age':'15\n'},{'name': 'Tomy', 'surname':'Tomson', 'age':'19'}]
How to only remove those '\n' only if they are present (which I am not sure how to check) and return a list consisted only from values that "clear from '\n' of dictionary? Thanks :)
with open("name.txt") as file:
for l in file:
listofdict.append(dict(zip(['name','surname','age']), l.split('|'))))
return listofdict
You could iterate through the dict.items() and strip the values to remove the carriage return, then use a list comprehension to do this for each dict
>>> [{key: val.strip() for key, val in i.items()} for i in listofdict]
[{'surname': 'Mikeson', 'age': '15', 'name': 'Mike'},
{'surname': 'Johnson', 'age': '15', 'name': 'John'},
{'surname': 'Tomson', 'age': '19', 'name': 'Tomy'}]
It's hard to say without seeing your file, but you could do this without any postprocessing by adjusting your file reading
with open("name.txt") as file:
listofdict = [dict(zip(['name','surname','age']), l.strip().split('|')) for l in file]
return listofdict

Categories

Resources