Filter List of Dictionaries and omit keys
Question:
I have a list of dictionaries:
resp = [
{
'meter_id': {'S': 'M#G000140'},
'meter_reading_reader': {'S': 'Meyer'},
'meter_reading_date': {'S': '2021-12-21T12:00:00'},
'item_type': {'S': 'READING'},
'meter_reading_value': {'S': '225'},
'meter_reading_unit': {'S': 'cbm'},
'meter_kind': {'S': 'Gas'},
'month': {'S': 'December'},
'year': {'S': '2021'},
'SK': {'S': 'MPID#P-00002-01-MG-001'},
'building_id': {'S': 'B#BUI-00001'},
'PK': {'S': 'READ#G000140#2021#Dec'},
'meter_serial_number': {'S': '7GMT0008942175'}
},
{
'meter_id': {'S': 'M#G000155'},
'meter_reading_reader': {'S': 'Meyer'},
'meter_reading_date': {'S': '2022-02-28T12:00:00'},
'item_type': {'S': 'READING'},
'meter_reading_value': {'S': '45'},
'meter_reading_unit': {'S': 'cbm'},
'meter_kind': {'S': 'Gas'},
'month': {'S': 'February'},
'year': {'S': '2022'},
'SK': {'S': 'MPID#P-00002-01-MG-001'},
'building_id': {'S': 'B#BUI-00001'},
'PK': {'S': 'READ#G000155#2022#Feb'},
'meter_serial_number': {'S': '7GMT0008942175'}
}
]
that I want to filter to show only 2 key-Value pairs – ‘meter_reading_date’ and ‘meter_reading_value’. So far I can filter with one value.
for item in resp:
details = item['meter_reading_value']
print(details)
That gives me:
{'S': '225'}
{'S': '45'}
{'S': '12'}
but what I want to achieve is the following:
{
'meter_reading_date': '2021-12-21T12:00:00',
'meter_reading_value': '225'
},
{
'meter_reading_date': '2022-02-28T12:00:00',
'meter_reading_value': '45'
},
How is that achievable?
Answers:
You can do something like that
lst = []
keys = ['meter_reading_date', 'meter_reading_value']
for item in resp:
d = {}
for key in keys:
d[key] = list(item[key].values())[0]
lst.append(d)
Or one liner with comprehensions
lst = [{key: list(item[key].values())[0] for key in keys} for item in resp]
Output
[{'meter_reading_date': '2021-12-21T12:00:00', 'meter_reading_value': '225'},
{'meter_reading_date': '2022-02-28T12:00:00', 'meter_reading_value': '45'}]
list(item[key].values())[0]
can be replaced with item[key]['S']
if this key is permanent.
-
Iterate through the list and then through the dict.
-
Create dict from the results and append to a list.
res = []
for z in d:
for y in z.values():
temp = {}
temp['meter_reading_date'] = y['S']
temp['meter_reading_value'] = y['S']
res.append(temp)
print(res)
With operator.itemgetter (to extract by parent/child keys):
from operator import itemgetter
keys = ('meter_reading_date', 'meter_reading_value')
p_keys, c_key = itemgetter(*keys), itemgetter('S')
res = [dict(zip(keys, (c_key(d_) for d_ in p_keys(d)))) for d in resp]
print(res)
[{'meter_reading_date': '2021-12-21T12:00:00', 'meter_reading_value': '225'}, {'meter_reading_date': '2022-02-28T12:00:00', 'meter_reading_value': '45'}]
There are a number of good answer here and they allow for easy extension via enumeration of keys. However, if you know the keys you are interested in and this is not too dynamic, I think the most straightforward thing to do is just use them:
res = [
{
"meter_reading_date" : item["meter_reading_date"]["S"],
"meter_reading_value" : item["meter_reading_value"]["S"],
}
for item in resp
]
print(res)
If the values (dictionaries) associated with meter_reading_date and meter_reading_value are guaranteed to have just one key – i.e., ‘S’ then:
KEYS = ('meter_reading_date', 'meter_reading_value')
output = [{k: d[k]['S'] for k in KEYS} for d in resp]
print(output)
Output:
[{'meter_reading_date': '2021-12-21T12:00:00', 'meter_reading_value': '225'}, {'meter_reading_date': '2022-02-28T12:00:00', 'meter_reading_value': '45'}]
I have a list of dictionaries:
resp = [
{
'meter_id': {'S': 'M#G000140'},
'meter_reading_reader': {'S': 'Meyer'},
'meter_reading_date': {'S': '2021-12-21T12:00:00'},
'item_type': {'S': 'READING'},
'meter_reading_value': {'S': '225'},
'meter_reading_unit': {'S': 'cbm'},
'meter_kind': {'S': 'Gas'},
'month': {'S': 'December'},
'year': {'S': '2021'},
'SK': {'S': 'MPID#P-00002-01-MG-001'},
'building_id': {'S': 'B#BUI-00001'},
'PK': {'S': 'READ#G000140#2021#Dec'},
'meter_serial_number': {'S': '7GMT0008942175'}
},
{
'meter_id': {'S': 'M#G000155'},
'meter_reading_reader': {'S': 'Meyer'},
'meter_reading_date': {'S': '2022-02-28T12:00:00'},
'item_type': {'S': 'READING'},
'meter_reading_value': {'S': '45'},
'meter_reading_unit': {'S': 'cbm'},
'meter_kind': {'S': 'Gas'},
'month': {'S': 'February'},
'year': {'S': '2022'},
'SK': {'S': 'MPID#P-00002-01-MG-001'},
'building_id': {'S': 'B#BUI-00001'},
'PK': {'S': 'READ#G000155#2022#Feb'},
'meter_serial_number': {'S': '7GMT0008942175'}
}
]
that I want to filter to show only 2 key-Value pairs – ‘meter_reading_date’ and ‘meter_reading_value’. So far I can filter with one value.
for item in resp:
details = item['meter_reading_value']
print(details)
That gives me:
{'S': '225'}
{'S': '45'}
{'S': '12'}
but what I want to achieve is the following:
{
'meter_reading_date': '2021-12-21T12:00:00',
'meter_reading_value': '225'
},
{
'meter_reading_date': '2022-02-28T12:00:00',
'meter_reading_value': '45'
},
How is that achievable?
You can do something like that
lst = []
keys = ['meter_reading_date', 'meter_reading_value']
for item in resp:
d = {}
for key in keys:
d[key] = list(item[key].values())[0]
lst.append(d)
Or one liner with comprehensions
lst = [{key: list(item[key].values())[0] for key in keys} for item in resp]
Output
[{'meter_reading_date': '2021-12-21T12:00:00', 'meter_reading_value': '225'},
{'meter_reading_date': '2022-02-28T12:00:00', 'meter_reading_value': '45'}]
list(item[key].values())[0]
can be replaced with item[key]['S']
if this key is permanent.
-
Iterate through the list and then through the dict.
-
Create dict from the results and append to a list.
res = []
for z in d:
for y in z.values():
temp = {}
temp['meter_reading_date'] = y['S']
temp['meter_reading_value'] = y['S']
res.append(temp)
print(res)
With operator.itemgetter (to extract by parent/child keys):
from operator import itemgetter
keys = ('meter_reading_date', 'meter_reading_value')
p_keys, c_key = itemgetter(*keys), itemgetter('S')
res = [dict(zip(keys, (c_key(d_) for d_ in p_keys(d)))) for d in resp]
print(res)
[{'meter_reading_date': '2021-12-21T12:00:00', 'meter_reading_value': '225'}, {'meter_reading_date': '2022-02-28T12:00:00', 'meter_reading_value': '45'}]
There are a number of good answer here and they allow for easy extension via enumeration of keys. However, if you know the keys you are interested in and this is not too dynamic, I think the most straightforward thing to do is just use them:
res = [
{
"meter_reading_date" : item["meter_reading_date"]["S"],
"meter_reading_value" : item["meter_reading_value"]["S"],
}
for item in resp
]
print(res)
If the values (dictionaries) associated with meter_reading_date and meter_reading_value are guaranteed to have just one key – i.e., ‘S’ then:
KEYS = ('meter_reading_date', 'meter_reading_value')
output = [{k: d[k]['S'] for k in KEYS} for d in resp]
print(output)
Output:
[{'meter_reading_date': '2021-12-21T12:00:00', 'meter_reading_value': '225'}, {'meter_reading_date': '2022-02-28T12:00:00', 'meter_reading_value': '45'}]