Hello I have below code where I am trying to add elements to a dict
for ent in NACLS:
set_filter = {'Name': 'network-acl-id', 'Values': [naclID]}
print(set_filter)
set_filter.update({'Name': 'entry.rule-number', 'Values': [str(ent[0])]})
print(set_filter)
The output for the above code is
{'Name': 'network-acl-id', 'Values': ['acl-08128a2540eb']}
{'Name': 'entry.rule-number', 'Values': ['50']}
{'Name': 'network-acl-id', 'Values': ['acl-08128a2540eb']}
{'Name': 'entry.rule-number', 'Values': ['60']}
{'Name': 'network-acl-id', 'Values': ['acl-08128a2540eb']}
{'Name': 'entry.rule-number', 'Values': ['70']}
Whereas I was wanting it to update the existing dictionary but somehow it's getting overwritten. Expected output
{'Name': 'network-acl-id', 'Values': ['acl-08128a2540eb']}, {'Name': 'entry.rule-number', 'Values': ['50']}
{'Name': 'network-acl-id', 'Values': ['acl-08128a2540eb']}, {'Name': 'entry.rule-number', 'Values': ['60']}
{'Name': 'network-acl-id', 'Values': ['acl-08128a2540eb']}, {'Name': 'entry.rule-number', 'Values': ['70']}
can someone please guide me on how I can achieve this?
The update method adds {key:value} pairs to a dictionary unless the key already exists, in which case it just updates the value to the new value.
From the look of your expected output it seems you want a list of dictionaries all with the same keys but different values.
try this:
set_filter = []
for ent in NACLS:
set_filter.append({'Name': 'network-acl-id', 'Values': [naclID]})
set_filter.append({'Name': 'entry.rule-number', 'Values': [str(ent[0])]})
print(set_filter)
I didn't understand what is the problem here. Do you want to print these dicts like you expected ?
You can write :
for ent in NACLS:
set_filter = {'Name': 'network-acl-id', 'Values': [naclID]}
print(set_filter,end=",")
set_filter.update({'Name': 'entry.rule-number', 'Values': [str(ent[0])]})
print(set_filter,end="\n")
The expected output example isn't a valid dictionary:
{'Name': 'network-acl-id', 'Values': ['acl-08128a2540eb']}, {'Name': 'entry.rule-number', 'Values': ['50']}
Reformatted:
{
'Name': 'network-acl-id',
'Values': [ 'acl-08128a2540eb' ]
},
{
'Name': 'entry.rule-number',
'Values': [ '50' ]
}
To create a list of dictionaries:
for ent in NACLS:
set_filter = [{'Name': 'network-acl-id', 'Values': [naclID]}]
# ^ note square brackets ^
print(set_filter)
set_filter.append({'Name': 'entry.rule-number', 'Values': [str(ent[0])]})
print(set_filter)
Or to put them all into a list:
set_filter = []
for ent in NACLS:
set_filter.append({'Name': 'network-acl-id', 'Values': [naclID]})
print(set_filter)
set_filter.append({'Name': 'entry.rule-number', 'Values': [str(ent[0])]})
print(set_filter)
I don't understand much about your purpose of the list of dictionary, the suggested code
set_filters = []
for ent in NACLS:
set_filters.append({'Name': 'network-acl-id', 'Values': [naclID]})
set_filters.append({'Name': 'entry.rule-number', 'Values': [str(ent[0])]})
is close to your idea. However, the two dictionaries you tried to gather in the list can be combined into just one:
set_filters = []
for ent in NACLS:
set_filters.append(
{
'network-acl-id': [naclID],
'entry.rule-number': [str(ent[0])]
}
)
From here, you can make it shorter as
set_filters = [
{ 'network-acl-id': [naclID], 'entry.rule-number': [str(ent[0])] } for ent in NACLS
]
Related
i have a list of dict like this
[
{'id': 'A123',
'feature': {'name': 'jack', 'age' : '18' },
'create_time': '2022-5-17 10:29:47',
'is_fast': False},
{'id': 'A123',
'feature': {'gender': 'male'},
'create_time': '2022-5-17 10:29:47',
'is_fast': False},
{'id': 'A123',
'habit': {'name': 'read'},
'create_time': '2022-5-15 10:29:45',
'is_fast': False},
{'id': 'A456',
'feature': {'name': 'rose'},
'create_time': '2022-4-15 10:29:45',
'is_fast': False},
{'id': 'A456',
'habit': {'name': 'sport'},
'create_time': '2022-3-15 10:29:45',
'is_fast': False}
]
But I want to merge the same "id" values together using something function
The desired output is as follows
[
{'id': 'A123',
'feature': {'name': 'jack', 'age' : '18' ,'gender': 'male'},
'habit': {'name': 'read'},
'create_time': '2022-5-19 10:29:47', #Get the latest time based on the same id
'is_fast': False},
{'id': 'A456',
'feature': {'name': 'rose'},
'habit': {'name': 'sport'},
'create_time': '2022-4-15 10:29:45',
'is_fast': False},
]
How can I merge the same "id" values according to these dictionaries..
This should get you started... I put some inline notes to explain what the code is doing. You still need to implement a date time comparison.
def merge_dicts(lst):
final = {} # results
for row in lst: # iterate through list
if row['id'] not in final: # if current item id hasnt been seen
final[row['id']] = row # assign it to results with id as the key
else:
record = final[row['id']] # otherwise compare to data already stored
for k,v in row.items(): #iterate through dictionary items
if k not in record: # if key not in results
record[k] = v # add the key and value
continue
if record[k] == v: continue # if they are already equal move on
if isinstance(v, dict): # if its a dictionary
record[k].update(v) # update the dictionary
else: # must be date time sequence so do some datetime comparison
"""Do some date comparison and assign correct date"""
return [v for k,v in final.items()] # convert to list
print(merge_dicts(lst))
output:
[
{
'id': 'A123',
'feature': {'name': 'jack', 'age': '18', 'gender': 'male'},
'create_time': '2022-5-17 10:29:47',
'is_fast': False,
'habit': {'name': 'read'}
},
{
'id': 'A456',
'feature': {'name': 'rose'},
'create_time': '2022-4-15 10:29:45',
'is_fast': False,
'habit': {'name': 'sport'}
}
]
You can use the dict.setdefault method to initialize sub-dicts under keys that don't already exist to avoid cluttering up your code with conditional statements that test the existence of keys:
merged = {}
for d in lst:
s = merged.setdefault(d['id'], d)
for k, v in d.items():
if isinstance(v, dict):
s.setdefault(k, v).update(v)
elif v > s[k]: # the dates/times in the input follow alphabetical order
s[k] = v # later dates/times takes precedence
print(list(merged.values()))
Demo: https://replit.com/#blhsing/BlandCarelessPolygons#main.py
Hello I have a situation where I am trying to make a filter in my code customizable so there is minimum duplication of code below is the code that I want to update
for ent in NACLS:
response = ec2.describe_network_acls(Filters=[{'Name': 'network-acl-id', 'Values': [naclID]},
{'Name': 'entry.rule-number', 'Values': [str(ent[0])]},
{'Name': 'entry.protocol', 'Values': [ProtoDict[ent[1]]]},
{'Name': 'entry.port-range.from', 'Values': [str(ent[2])]},
{'Name': 'entry.port-range.to', 'Values': [str(ent[2])]},
{'Name': 'entry.rule-action', 'Values': ["deny"]},
])
I want the filter to customizable for example
for ent in NACLS:
if add = True:
response = ec2.describe_network_acls(Filters=[{'Name': 'network-acl-id', 'Values': [naclID]},
{'Name': 'entry.rule-number', 'Values': [str(ent[0])]},
])
else:
response = ec2.describe_network_acls(Filters=[{'Name': 'network-acl-id', 'Values': [naclID]},
{'Name': 'entry.rule-number', 'Values': [str(ent[0])]},
{'Name': 'entry.protocol', 'Values': [ProtoDict[ent[1]]]},
{'Name': 'entry.port-range.from', 'Values': [str(ent[2])]},
{'Name': 'entry.port-range.to', 'Values': [str(ent[2])]},
{'Name': 'entry.rule-action', 'Values': ["deny"]},
])
This is what I was wanting to do but doesn't work please let me know if there is a better way to achieve this
for ent in NACLS:
filters = {'Name': 'network-acl-id', 'Values': [naclID]}, {'Name': 'entry.rule-number', 'Values': [str(ent[0])]}
filters = filters + tuple({'Name': 'entry.protocol', 'Values': [ProtoDict[ent[1]]]}) //we can add more but this was just to test
print(str(filters)[1:-1])
The output for this is -
{'Name': 'network-acl-id', 'Values': ['acl-08128a2540']}, {'Name': 'entry.rule-number', 'Values': ['80']}, 'Name', 'Values'
When I try to add the value in tuple it shows as blank can someone please guide me on what I am doing wrong here?
I suspect that by adding tuples, you meant to add the dictionary to the tuple of filters, which is not what you are doing in your current script. I suggest that you replace
filters = filters + tuple({'Name': 'entry.protocol', 'Values': [ProtoDict[ent[1]]]})
with
filters = filters + ({'Name': 'entry.protocol', 'Values': [ProtoDict[ent[1]]]},)
I am trying to figure out how to filter for the dictionaries that have a status of "awaiting_delivery". I am not sure how to do this (or if it is impossible). I am new to python and programming. I am using Python 3.8.5 on VS Code on Ubuntu 20.04. The data below is sample data that I created that resembles json data from an API. Any help on how to filter for "status" would be great. Thank you.
nested_dict = {
'list_data': [
{
'id': 189530,
'total': 40.05,
'user_data': {
'id': 1001,
'first_name': 'jane',
'last_name': 'doe'
},
'status': 'future_delivery'
},
{
'id': 286524,
'total': 264.89,
'user_data': {
'id': 1002,
'first_name': 'john',
'last_name': 'doe'
},
'status': 'awaiting_delivery'
},
{
'id': 368725,
'total': 1054.98,
'user_data': {
'id': 1003,
'first_name': 'chris',
'last_name': 'nobody'
},
'status': 'awaiting_delivery'
},
{
'id': 422955,
'total': 4892.78,
'user_data': {
'id': 1004,
'first_name': 'mary',
'last_name': 'madeup'
},
'status': 'future_delivery'
}
],
'current_page': 1,
'total': 2,
'first': 1,
'last': 5,
'per_page': 20
}
#confirm that nested_dict is a dictionary
print(type(nested_dict))
#create a list(int_list) from the nested_dict dictionary
int_list = nested_dict['list_data']
#confirm that int_list is a list
print(type(int_list))
#create the int_dict dictionary from the int_list list
for int_dict in int_list:
print(int_dict)
#this is my attempt at filtering the int_dict dictionar for all orders with a status of awaiting_delivery
for order in int_dict:
int_dict.get('status')
print(order)
Output from Terminal Follows:
<class 'dict'>
<class 'list'>
{'id': 189530, 'total': 40.05, 'user_data': {'id': 1001, 'first_name': 'jane', 'last_name': 'doe'}, 'status': 'future_delivery'}
{'id': 286524, 'total': 264.89, 'user_data': {'id': 1002, 'first_name': 'john', 'last_name': 'doe'}, 'status': 'awaiting_delivery'}
{'id': 368725, 'total': 1054.98, 'user_data': {'id': 1003, 'first_name': 'chris', 'last_name': 'nobody'}, 'status': 'awaiting_delivery'}
{'id': 422955, 'total': 4892.78, 'user_data': {'id': 1004, 'first_name': 'mary', 'last_name': 'madeup'}, 'status': 'future_delivery'}
id
total
user_data
status
You can obtain a filtered list of dicts by doing conditional list comprehension on your list of dicts:
# filter the data
list_data_filtered = [entry for entry in nested_dict['list_data']
if entry['status'] == 'awaiting_delivery']
# print out the results
for entry in list_data_filtered:
print(entry)
# results
# {'id': 286524, 'total': 264.89, 'user_data': {'id': 1002, 'first_name': 'john', 'last_name': 'doe'}, 'status': 'awaiting_delivery'}
# {'id': 368725, 'total': 1054.98, 'user_data': {'id': 1003, 'first_name': 'chris', 'last_name': 'nobody'}, 'status': 'awaiting_delivery'}
This is very similar to https://github.com/defunkt/pystache/issues/157, however in the mentioned post didn't really answer...
My target: print the following lines:
Al,John,Jack
Tim,Tom,Todd
without a final comma.
I tried this way:
ctx = {
'gangs': [
{'gangsters': [ {'name': 'Al' }, {'name': 'John'}, {'name': 'Jack'}]},
{'gangsters': [ {'name': 'Tim'}, {'name': 'Tom'} , {'name': 'Todd'}]},
]
}
class Lambdas(object):
def __init__(self, renderer):
self.renderer = renderer
def rstrip(self):
"Remove last character"
print self.renderer.context
return lambda s: self.renderer.render(s, self.renderer.context)[:-1]
renderer = pystache.Renderer(missing_tags='strict')
print renderer.render("""
{{#gangs}}
{{#rstrip}}{{#gangsters}}{{name}},{{/gangsters}}{{/rstrip}}
{{/gangs}}
""", ctx, Lambdas(renderer))
The output:
ContextStack({'gangs': [{'gangsters': [{'name': 'Al'}, {'name': 'John'}, {'name': 'Jack'}]}, {'gangsters': [{'name': 'Tim'}, {'name': 'Tom'}, {'name': 'Todd'}]}]}, <__main__.Lambdas object at 0x15cadb10>, {'gangsters': [{'name': 'Al'}, {'name': 'John'}, {'name': 'Jack'}]})
ContextStack({'gangs': [{'gangsters': [{'name': 'Al'}, {'name': 'John'}, {'name': 'Jack'}]}, {'gangsters': [{'name': 'Tim'}, {'name': 'Tom'}, {'name': 'Todd'}]}]}, <__main__.Lambdas object at 0x15cadb10>, {'gangsters': [{'name': 'Al'}, {'name': 'John'}, {'name': 'Jack'}]})
Al,John,Jack
Al,John,Jack
The culprit is the invocation to render() inside rstrip. Notice how, during the second call, the 3d element of the ContextStack is exactly identical to the previous call.
Is this a bug, or am I missing something?!?
Answered upstream: https://github.com/defunkt/pystache/issues/158
def rstrip(self):
"Remove last character"
return lambda s: copy.deepcopy(self.renderer).render(s, self.renderer.context)[:-1]
I have the following structure:
[
{
u'123456': {'name': "Bill"},
u'234567': {'name': "Dave"},
u'345678': {'name': "Tom"}
},
]
During a for loop new items are added to the list using the extend function. Unfortunately this results in the following structure:
[
{
u'123456': {'name': "Bill"},
u'234567': {'name': "Dave"},
u'345678': {'name': "Tom"}
},
{
u'555555': {'name': "Steve"},
u'666666': {'name': "Michael"},
u'777777': {'name': "George"}
}
]
The intended result is actually a flat structure such in the following:
[
{
u'123456': {'name': "Bill"},
u'234567': {'name': "Dave"},
u'345678': {'name': "Tom"},
u'555555': {'name': "Steve"},
u'666666': {'name': "Michael"},
u'777777': {'name': "George"}
}
]
Is it possible to append to the list so that the structure gets built in a flat way.
or
Is it possible to flatten after the loop has finished?
If your list is named l you could use l[0].update(new_dict).
Example:
l = [{u'123456': {'name': "Bill"}}]
l[0].update({u'234567': {'name': "Dave"}})
print(l)
Nice formatted output is:
[
{
u'123456': {'name': 'Bill'},
u'234567': {'name': 'Dave'}
}
]
Where you currently have something like this:
mylist.extend(newdict)
You should use this:
mylist[0].update(newdict)
You can add the items of both dictionaries together:
>>> mylist = [
{
u'123456': {'name': "Bill"},
u'234567': {'name': "Dave"},
u'345678': {'name': "Tom"}
},
]
>>> mydict = {
u'555555': {'name': "Steve"},
u'666666': {'name': "Michael"},
u'777777': {'name': "George"}
}
>>> [dict(mylist[0].items() + mydict.items())]
[{u'123456': {'name': 'Bill'}, u'555555': {'name': 'Steve'}, u'777777': {'name': 'George'}, u'666666': {'name': 'Michael'}, u'345678': {'name': 'Tom'}, u'234567': {'name': 'Dave'}}]
Although it's more clean to just do .update():
>>> mylist[0].update(mydict)
You can use .update(), however this will overwrite values if you'll have duplicated keys.
def flatten(results):
newresult = {}
for subdict : results:
newresult.update(subdict)
return [newresult]