Python Iterate over dictionary and update another dictionary - python

I have list (of dictionary) and dictionary in Python as below
List1= [ { 'Id': 'i-0f76fasa','Port': 80,'State': 'unavailable','TargetGrnArn' :'ABC123'}
{ 'Id': 'i-0f97wewr','Port': 88,'State': 'unavailable','TargetGrnArn' :'ABC123'}
{ 'Id': 'i-0f12xrde','Port': 90,'State': 'unavailable','TargetGrnArn' :'XYZ234'}
{ 'Id': 'i-0f26fade','Port': 90,'State': 'unavailable','TargetGrnArn' :'XYZ234'}]
Dict1={"TargetGroupName":1245,"TargetGroupArn": ABC123,"HealthCheckProtocol":TCP,"HealthCheckPort":22,"HealthCheckEnabled":YES,"HealthCheckIntervalSeconds":20,"HealthCheckTimeoutSeconds":60,"HealthyThresholdCount":3,"HealthCheckPath":/tmp}
The requirement is TargetGrnArn is matched with List new list or dictionary should have 2 items with same values as in Dict1 in addition to values in List1.
final output requirement is
{"TargetGroupName":1245,"TargetGroupArn": ABC123,"HealthCheckProtocol":TCP,"HealthCheckPort":22,"HealthCheckEnabled":YES,"HealthCheckIntervalSeconds":20,"HealthCheckTimeoutSeconds":60,"HealthyThresholdCount":3,"HealthCheckPath":/tmp ,'Id': 'i-0f76fasa','Port': 80,'State': 'unavailable'}
{"TargetGroupName":1245,"TargetGroupArn": ABC123,"HealthCheckProtocol":TCP,"HealthCheckPort":22,"HealthCheckEnabled":YES,"HealthCheckIntervalSeconds":20,"HealthCheckTimeoutSeconds":60,"HealthyThresholdCount":3,"HealthCheckPath":/tmp , 'Id': 'i-0f97wewr','Port': 88,'State': 'unavailable'}
Here Information in Dict1 will remain same in both the items but rest information from list will be different.

Related

Sort list of dictionaries by key [duplicate]

This question already has answers here:
How do I sort a dictionary by key?
(32 answers)
Apply function to each element of a list
(4 answers)
Closed 5 months ago.
I have a list of dictionaries where the order of the keys is not consistent. Ideally I would like 'vid' to always come first with 'name' being second. As you can see below, sometimes 'name' comes first. How can I sort this list of dictionaries to always have 'vid' first?
viri_assets = [
{'vid': 'transpower_036', 'name': '221_02_PB_520_REF_174050'},
{'name': '242_07_DINA_HSTLR_YT_210238', 'vid': 'transpower_168'},
{'vid': 'transpower_170', 'name': '242_08_DINA_HSTLR_YT_210220'},
{'name': '251_PS04_PB_520_REF_109968', 'vid': 'transpower_166'},
{'vid': 'transpower_165', 'name': '251_PS05_PB_520_REF_109967'},
{'name': '31089', 'vid': 'transpower_064'}]
I have tried using sorted(viri_assets, key=lambda d: list(d.keys())) but it does not work.
You don't want to call sorted on your list, but on each dict of the list
Use .items() to get key-value pairs for each dict, and it'll sort them by the first element of the pair: the key. Set reverse to True to get "vid" before "name".
viri_assets = [{'vid': 'transpower_036', 'name': '221_02_PB_520_REF_174050'},
{'vid': 'transpower_065', 'name': '222_05_KAL_T2E_YT_344991'},
{'name': '226_02_INTL_PRSTR_ET_499802', 'vid': 'transpower_156'}]
viri_assets = [dict(sorted(d.items(), reverse=True)) for d in viri_assets]
print(viri_assets)
Output:
[{'vid': 'transpower_036', 'name': '221_02_PB_520_REF_174050'},
{'vid': 'transpower_065', 'name': '222_05_KAL_T2E_YT_344991'},
{'vid': 'transpower_156', 'name': '226_02_INTL_PRSTR_ET_499802'}]

Need to filter list of dictionaries

I have one large list of dictionaries pulled from a database. I'm wondering if there is a way to search the first list of dicts to only show the first 3 digits (list would be unique to avoid duplicate entries) in one dropdown menu and, based on the selection, show the appropriate options?
Essentially the first dropdown would show selectable options "220, 221, 222, 223, 224", let's say we selected "220", then the second dropdown would show '220_2_INTL_PRSTR_ET_619076', '220_4_KAL_T2E_DOLE_344657'. I'm not worried about the code needed to create the dropdowns, just the filtering of the list of dicts to achieve the results.
list_of_dict = [
{'label': '220_2_INTL_PRSTR_ET_619076', 'value': '220_2_INTL_PRSTR_ET_619076'},
{'label': '220_4_KAL_T2E_DOLE_344657', 'value': '220_4_KAL_T2E_DOLE_344657'},
{'label': '221_1_PB_520_REF_174049', 'value': '221_1_PB_520_REF_174049'},
{'label': '222_5_KAL_T2E_YT_344991', 'value': '222_5_KAL_T2E_YT_344991'},
{'label': '223_2_PB_520_REF_174050', 'value': '223_2_PB_520_REF_174050'}, ,
{'label': '224_3_PB_520_REF_174051', 'value': '224_3_PB_520_REF_174051'}]
It's fairly straightforward to turn your list into a dictionary that has exactly what you need:
list_of_dict = [
{'label': '220_2_INTL_PRSTR_ET_619076', 'value': '220_2_INTL_PRSTR_ET_619076'},
{'label': '220_4_KAL_T2E_DOLE_344657', 'value': '220_4_KAL_T2E_DOLE_344657'},
{'label': '221_1_PB_520_REF_174049', 'value': '221_1_PB_520_REF_174049'},
{'label': '222_5_KAL_T2E_YT_344991', 'value': '222_5_KAL_T2E_YT_344991'},
{'label': '223_2_PB_520_REF_174050', 'value': '223_2_PB_520_REF_174050'},
{'label': '224_3_PB_520_REF_174051', 'value': '224_3_PB_520_REF_174051'}
]
# it's a "one-liner", a dict comprehension split over a few lines for readability:
result = {
p: [d for d in list_of_dict if d['label'].startswith(p)]
for p in set(d['label'][:3] for d in list_of_dict)
}
print(result['220']) # the contents for this prefix
print(result.keys()) # the keys for your first dropdown
Output:
[{'label': '220_2_INTL_PRSTR_ET_619076', 'value': '220_2_INTL_PRSTR_ET_619076'}, {'label': '220_4_KAL_T2E_DOLE_344657', 'value': '220_4_KAL_T2E_DOLE_344657'}]
['222', '220', '224', '223', '221']
Note that the keys are out of order, but sorting is straightforward.
Instead of d['label'][:3] you could consider d['label'].split('_')[0], if the prefixes aren't all 3 characters long, but instead are "everything before the first underscore".
Edit: in the comments, you asked for some additional explanation of the core bit of code:
{
p: [d for d in list_of_dict if d['label'].startswith(p)]
for p in set(d['label'][:3] for d in list_of_dict)
}
Anything of the form {..: .. for .. in ..} is a dictionary comprehension, constructing a dictionary using a very efficient loop.
Here it's {p: ... for p in set(d['label'][:3] for d in list_of_dict)}. So, p loops over the elements of set(d['label'][:3] for d in list_of_dict) and for every p, a key is added to the dictionary.
That d['label'][:3] for d in list_of_dict is a generator expression that generates the first three characters ([:3]) of every 'label' value for every dictionary d in your list_of_dict. I.e. ['220', '220', '221', '222', etc.]. And the set() around it reduces it to have only unique elements.
The value part of the dictionary comprehension is a list comprehension, so a list is construction as a value for each key p. A list comprehension looks like [.. for .. in ..] (with an optional if ..-part to filter the contents)
The comprehension [d for d in list_of_dict if d['label'].startswith(p)] takes each dictionary d from your list_of_dict, but only keeps it in the resulting list if d['label'].startswith(p) is True (i.e. only if d['label'] starts with p, which is the current 3-letter string being used as a key.
So, it gathers all of the 3-letter prefixes in a set, and then generates a dictionary with those unique prefixes as keys, and a list of all the dictionaries that have 'label' values starting with the matching 3-letter prefix, as their value.
Given a prefix, the filtering code comes down to an if-statement and a str.startwith() test:
prefix = '220'
for d in list_of_dict:
if d['label'].startswith(prefix):
print(d)
For purposes of a dropdown menu, it may be preferable to group the data in advance using defaultdict() and extracting the prefix with slicing:
from collections import defaultdict
grouped = defaultdict(list)
for d in list_of_dict:
prefix = d['label'][:3]
grouped[prefix].append( d['value'])
Now you can lookup results directly:
>>> grouped['220']
['220_2_INTL_PRSTR_ET_619076', '220_4_KAL_T2E_DOLE_344657']
This strategy is also faster than filtering the entire list for every lookup.
As first step, you can use set() to obtain the first tree characters from labels without duplicates.
Then you can create a function to filter the list using str.startswith:
def get_options(l):
return {d["label"][:3] for d in l}
def filter_list(l, s):
return [d for d in l if d["label"].startswith(s)]
print(get_options(list_of_dict))
print(filter_list(list_of_dict, "220"))
Prints:
{"222", "221", "224", "220", "223"}
[
{
"label": "220_2_INTL_PRSTR_ET_619076",
"value": "220_2_INTL_PRSTR_ET_619076",
},
{
"label": "220_4_KAL_T2E_DOLE_344657",
"value": "220_4_KAL_T2E_DOLE_344657",
},
]

Python efficiently getting a specific value from a list of dictionaries

I am using an API to get results from a database that is returned in JSON format. I'm then trying to just extract certain keys/values and append them to a blank list. The field I want is eissn and the API returns results like this:
[
{'type': 'doi', 'id': '10.16472/j.chinatobacco.2017.045'},
{'type': 'pissn', 'id': '1004-5708'},
{'type': 'eissn', 'id': '1004-5708'}
]
I want to extract the eissn id which i have tried using this code:
deissnlist = []
for i in range(0,lengthD):
deissnlist.append(doajresult[i]['bibjson']['identifier'][3]
['id'])
Where lengthD/i are the number of results returned from the API. The problem is that the eissn ID is not always the 3rd dictionary in the list. Is there any way I can search the tuples and only get the eissn ID without using another for loop (and thus going from O(n) to O(n^2)? The expected output is just the single value of the eissn id (in this case 1004-5708)
I tried converting the list to a dictionary but that didn't work because it treated each tuple as it's own dictionary. Thanks!
I may have misunderstood question and over simplified; but, if you are looking to simply extract a list of the ids from that sample input, this is how I would do it:
input = [
{'type': 'doi', 'id': '10.16472/j.chinatobacco.2017.045'},
{'type': 'pissn', 'id': '1004-5708'},
{'type': 'eissn', 'id': '1004-5708'}
]
result = [x.get('id') for x in input]
print(result)
['10.16472/j.chinatobacco.2017.045', '1004-5708', '1004-5708']
Or for just the ids where type is eissn:
result = [x.get('id') for x in input if x.get('type') == 'eissn']

Python dictionary comprehension checking if something doesn't exist and setting a value

I have a dictionary that looks like this
old_dict = {"language":"english","gender":"female","job":"ceo"}
The only keys i'm interested in are
"language","job","hobby"
Filtering out using this logic only works for the keys that exist in my original dictionary.
dict_you_want = { your_key: old_dict[your_key] for your_key in your_keys if your_key in your_keys }
How can I alter this code to add conditions, if the key doesn't exist to set a null/none value to the key.
your_keys = ["language","job"]
The output i'm looking for is
{"language":"english","job":"ceo","hobby":None}
{ key:old_dict.get(key,None) for key in ["language","job", "hobby"]}
output:
{'hobby': None, 'job': 'ceo', 'language': 'english'}

How to append items from a list into a dictionary?

I'm very new to programming and Python and trying to figure things out. I'm trying to take items out of a list and append the keys and values to a dictionary but I can't figure out how. I tried using the dictionary's Update method but I'm only getting the last item from my list, not all the items. Here is my code:
a = {}
names = [ {'name': 'Bart'}, {'name': 'Lisa'}, {'name': 'Maggie'} ]
for name in names:
a.update(name)
The result I'm getting back is:
{'name': 'Maggie'}
But I want this in my new dictionary:
{'name': 'Bart'}, {'name': 'Lisa'}, {'name': 'Maggie'}
I wanted to put the items from the list inside the dictionary in order to access the values. I need all of the names but maybe there is a much easier way to do it.
Any hints would be great. Thanks.
With same key value you cant update a dict from list of dict. You can get a dict with key a list of values.
{'name': ['Bart', 'Lisa', 'Maggie']}
a={}
for n in names:
... for k in n:
... for k,v in [(k,n[k])]:
... if k not in a:a[k]=[v]
... else: a[k].append(v)

Categories

Resources