I have a list that contains multiple small dictionaries, something like this:
_history = [{ "field" : "field01", "mode" : "write"},
{ "field" : "field02", "mode" : "write"},
{ "field" : "field03", "mode" : "write"},
{ "field" : "field01", "mode" : "clear"}]
What I'm interested in is the best way to process the list of dictionaries and determine if the same field value shows up more than once (in this case 'field01') and if it does, I'd like to verify whether the mode is the same. In the example above, I have a conflict on field01 and I'd like to raise an exception
You can do the following:
from itertools import groupby
from operator import itemgetter
def validate(hist)
key = itemgetter('field')
for k, g in groupby(sorted(hist, key=key), key=key):
s = set(d['mode'] for d in g)
if len(s) > 1:
raise ValueError(k)
>>> validate(_history)
Traceback ...
ValueError: field01
Related
I have a dictionary similar to the below structure
sample_dict = {
'key1' : 'getVal1' ,
'key2' : 'getVal2' ,
'level1' :
{
'key3' : 'getVal3' ,
'level2' :
{
'key4' : 'getVal4'
}
}
}
I want to evaluate entire dictionary without accessing individual inner dict separately. (Eg : Without accessing 'level1' and 'level2' keys.)
The values are separate functions.. example is mentioned below.
def getVal1():
return "Some Calculation"
If it was a simple dict without nesting, it would be very simple to process, something like below.
final_dict = {k : eval(v) for k,v in sample_dict .items()}
But with nested dictionary, I am not able to construct.
If there is any generic way for this, it will be really helpful.
Working on something for fun...completely new to programming. How do I access the values in the dictionary so I can either add the cost values or check if its a "Main" or "Side" item, etc.
from collections import OrderedDict
#Items on menu
item1 = OrderedDict(name = "Regular Pizza",
cost = 20,
item_type = "Main",
size = "Regular")
item2 = OrderedDict(name = "Regular Salad",
cost = 5,
item_type = "Side",
size = "Regular")
Well, first things first.
I see that you are using OrderedDict from collections instead of just using dict. Don't do it, as you are new to Dictionary you should start from "vanilla dict" in my opinion.
OrderedDict as the name suggests is meant to preserve the order of the elements inside it.
But, after Python 3.5 the order preservation feature was implemented to dict, read more in this answer - Difference between dict and ordered dict
Also, as we access the dictionary values by their key, i don't think the order has much use here.
Now for your question on how to access the dictionary elements. Going from your example you have 2 items in the menu.
item1 = {
'name' : 'Regular Pizza',
'cost' : 20,
'item_type' : 'Main',
'size' : 'Regular'
}
item2 = {
'name' : 'Regular Salad',
'cost' : 5,
'item_type' : 'Side',
'size' : 'Regular'
}
Here i have created a dictionary with 2 items. Now
Check if the dish is main or not.
print ('The item is a ' + item1['item_type']+ ' dish')
Adding cost to items.
# increase item1 cost by 5
item1['cost'] += 5
Tip: Further you can put all the dishes inside a list and access them directly by the index values, with that you won't have to create multiple variables such as item1, item2...
The implemention would be like-
food = [
{ 'name' : 'Regular Pizza',
'cost' : 20,
'item_type' : 'Main',
'size' : 'Regular'}
,
{ 'name' : 'Regular Salad',
'cost' : 5,
'item_type' : 'Side',
'size' : 'Regular'}
]
Now to access the elements-
print ('The item is a ' + food[0]['item_type']+ ' dish')
food[0]['cost'] += 5
Suppose I have nested map like this
def someMap = [
a : [
b : [
c : "value",
d : "anothervalue"
]
]
]
I get the key at runtime as a string. Say it is "a.b.c"
How can I pull the value out of the map?
I know I can do myMap.a.b.c but for me, "a.b.c" is single string, I found out about at runtime?
Thanks
You could just go down the nodes likes this and try to get the respective child:
def key = "a.b.c"
def entry = someMap
key.split('\\.').each { entry = entry?.get(it) }
println entry?.value
I want to loop through a map so if regex condition/pattern is met I will put the value into another map, else I will put in the map {trigger-all=true}.
This is what I got so far :
def patternsFunc = [
/(?s).*vee\/.*/ : "vee",
/(?s).*$HelmServicesPath\/vee\/.*/ : "vee",
/(?s).*rest\/.*/ : "rest",
/(?s).*$HelmServicesPath\/rest\/.*/ : "rest",
/(?s).*service\/.*/ : "service",
/(?s).*$HelmServicesPath\/service\/.*/ : "service",
]
patternsFunc.find { pattern, cname ->
if (file.find(pattern)) {
triggermap."trigger-${cname}" = true
assert triggermap."trigger-${cname}"
return true //found
} else {
return false
}
}
But there are 2 problems with this code:
the loop here going through every item on the patternsFunc map, so everything I put inside the "else" will happen whenever any of the conditions aren't met for every Item and not on the entire maps I need.
How do I put all values from the array to the map inside the "else"?
What I really need to achieve is in case no conditions are met, This will be the content of the map: {trigger-all=true}.
And when a condition(let's say "vee" and "rest") is met, This will be the content of the map: {trigger-rest=true,trigger-vee=true}.
First of all, find
finds the first result, but you want to find all, so use findAll.
Next don't mix side-effects into find or alike. Do the "finding"
first, then deal with the results. In this case, you want to build a
map from all the results. Use collectEntries for that.
And finally
you want a fallback, if nothing is found. So you can use the elvis
operator ?: to provide an alternative, if the resulting map is empty.
E.g.
def patterns = [
(/(?s).*service\/.*/): "service",
]
def file = '/service/'
def triggerMap = patterns.findAll{ // find relevant map entries
file.find(it.key)
}.collectEntries{ // build your map
["trigger-${it.value}", true]
} ?: ["trigger-all": true] // provide a fallback
Alternatively to what cfrick suggested, you can use inject method with an empty map as the initial value. That way you can iterate over all patterns, add entries if the pattern is found, and in the end, you can return ["trigger-all": true] map if no pattern was found.
Below you can find an example that tests 3 different file paths.
def patternsFunc = [
/(?s).*vee\/.*/ : "vee",
/(?s).*rest\/.*/ : "rest",
/(?s).*service\/.*/ : "service"
]
def files = [
"/tmp",
"/tmp/vee/1",
"/tmp/vee/rest/1"
]
files.each { file ->
def result = patternsFunc.inject([:]) { map, pattern, cname ->
file.find(pattern) ? map + ["trigger-$cname": true] : map
} ?: ["trigger-all": true]
println "Result for $file: $result"
}
I'm still trying to figure it out how nested dictionaries in python really works.
I know that when you're using [] it's a list, () it's a tuple and {} a dict.
But when you want to make a nested dictionaries like this structure (that's what a i want) :
{KeyA :
{ValueA :
[KeyB : ValueB],
[Keyc : ValueC],
[KeyD : ValueD]},
{ValueA for each ValueD]}}
For now I have a dict like:
{KeyA : {KeyB : [ValueB],
KeyC : [ValueC],
KeyD : [ValueD]}}
Here's my code:
json_file = importation()
dict_guy = {}
for key, value in json_file['clients'].items():
n_customerID = normalization(value['shortname'])
if n_customerID not in dict_guy:
dict_guy[n_customerID] = {
'clientsName':[],
'company':[],
'contacts':[], }
dict_guy[n_customerID]['clientsName'].append(n_customerID)
dict_guy[n_customerID]['company'].append(normalization(value['name']))
dict_guy[n_customerID]['contacts'].extend([norma_email(item) for item in v\
alue['contacts']])
Can someone please, give me more informations or really explain to me how a nested dict works?
So, I hope I get it right from our conversation in the comments :)
json_file = importation()
dict_guy = {}
for key, value in json_file['clients'].items():
n_customerID = normalization(value['shortname'])
if n_customerID not in dict_guy:
dict_guy[n_customerID] = {
'clientsName':[],
'company':[],
'contacts':{}, } # Assign empty dict, not list
dict_guy[n_customerID]['clientsName'].append(n_customerID)
dict_guy[n_customerID]['company'].append(normalization(value['name']))
for item in value['contacts']:
normalized_email = norma_email(item)
# Use the contacts dictionary like every other dictionary
dict_guy[n_customerID]['contacts'][normalized_email] = n_customerID
There is no problem to simply assign a dictionary to a key inside another dictionary. That's what I do in this code sample. You can create dictionaries nested as deep as you wish.
How that this helped you. If not, we'll work on it further :)
EDIT:
About list/dict comprehensions. You are almost right that:
I know that when you're using [] it's a list, () it's a tuple and {} a dict.
The {} brackets are a little tricky in Python 3. They can be used to create a dictionary as well as a set!
a = {} # a becomes an empty dictionary
a = set() # a becomes an empty set
a = {1,2,3} # a becomes a set with 3 values
a = {1: 1, 2: 4, 3: 9} # a becomes a dictionary with 3 keys
a = {x for x in range(10)} # a becomes a set with 10 elements
a = {x: x*x for x in range(10)} # a becomes a dictionary with 10 keys
Your line dict_guy[n_customerID] = { {'clientsName':[], 'company':[], 'contacts':[]}} tried to create a set with a single dictionary in it and because dictionaries are not hashable, you got the TypeError exception informing you that something is not hashable :) (sets can store only ements that are hashable)
Check out this page.
example = {'app_url': '', 'models': [{'perms': {'add': True, 'change': True,
'delete': True}, 'add_url': '/admin/cms/news/add/', 'admin_url': '/admin/cms/news/',
'name': ''}], 'has_module_perms': True, 'name': u'CMS'}