I have a case where I need to construct following structure programmatically (yes I am aware of .setdefault and defaultdict but I can not get what I want)
I basically need a dictionary, with a dictionary of dictionaries created within the loop.
At the beginning the structure is completely blank.
structure sample (please note, I want to create an array that has this structure in the code!)
RULE = {
'hard_failure': {
4514 : {
'f_expr' = 'ABC',
'c_expr' = 'XF0',
}
}
}
pseudo code that needs to create this:
...
self.rules = {}
for row in rows:
a = 'hard_failure'
b = row[0] # 4514
c = row[1] # ABC
d = row[2] # XF0
# Universe collapse right after
self.rules = ????
...
The code above is obviously not working since I dont know how to do it!
Example, that you've posted is not a valid python code, I could only imagine that you're trying to do something like this:
self.rules[a] = [{b:{'f_expr': c, 'c_expr': d}}]
this way self.rules is a dictionary of a list of a dictionary of a dictionary. I bet there is more sane way to do this.
rules = {}
failure = 'hard_failure'
rules[failure] = []
for row in rows:
#this is what people are referring to below. You left out the addition of the dictionary structure to the list.
rules[failure][row[0]] = {}
rules[failure][row[0]]['type 1'] = row[1]
rules[failure][row[0]]['type 2'] = row[2]
This is what I created based on how I understood the questions. I wasn't sure what to call the 'f_expr' and 'c_expr' since you never mention where you get those but I assume they are already know column names in a resultset or structure of some sort.
Just keep adding to the structure as you go.
Your example code doesn't seem to be valid Python. It's not clear if the second level element is supposed to be a list or a dictionary.
However, if you're doing what I think you're doing, and it's a dictionary, you could use a tuple as a key in the top-level dictionary instead of nesting dictionaries:
>>> a = 'hard_failure'
>>> b = 4514
>>> c = "ABC"
>>> d = "XF0"
>>> rules = {}
>>> rules[(a,b)] = {'f_expr' : a,'c_expr' : d}
>>> rules
{('hard_failure', 4514): {'c_expr': 'XF0', 'f_expr': 'hard_failure'}}
My favorite way to deal with nested dictionaries & lists of dictionaries is to use PyYAML. See this response for details.
Well, I apologize for the confusion, I never claimed that code actually compiled, hence (pseudo). Arthur Thomas put me on the right track, here is slightly modified version. (Yes, now its a simply nested dictionary, 3 levels down)
RULE_k = 'hard_failure'
self.rules = {}
for row in rows:
self.rules_compiled.setdefault(RULE_k, {})
self.rules_compiled[RULE_k][row[1]] = {}
self.rules_compiled[RULE_k][row[1]]['f_expr'] = row[0]
self.rules_compiled[RULE_k][row[1]]['c_expr'] = row[1]
Related
I am working on a code which pulls data from database and based on the different type of tables , store the data in dictionary for further usage.
This code handles around 20-30 different table so there are 20-30 dictionaries and few lists which I have defined as class variables for further usage in code.
for example.
class ImplVars(object):
#dictionary capturing data from Asset-Feed table
general_feed_dict = {}
ports_feed_dict = {}
vulns_feed_dict = {}
app_list = []
...
I want to clear these dictionaries before I add data in it.
Easiest or common way is to use clear() function but this code is repeatable as I will have to write for each dict.
Another option I am exploring is with using dir() function but its returning variable names as string.
Is there any elegant method which will allow me to fetch all these class variables and clear them ?
You can use introspection as you suggest:
for d in filter(dict.__instancecheck__, ImplVars.__dict__.values()):
d.clear()
Or less cryptic, covering lists and dicts:
for obj in ImplVars.__dict__.values():
if isinstance(obj, (list, dict)):
obj.clear()
But I would recommend you choose a bit of a different data structure so you can be more explicit:
class ImplVars(object):
data_dicts = {
"general_feed_dict": {},
"ports_feed_dict": {},
"vulns_feed_dict": {},
}
Now you can explicitly loop over ImplVars.data_dicts.values and still have other class variables that you may not want to clear.
code:
a_dict = {1:2}
b_dict = {2:4}
c_list = [3,6]
vars_copy = vars().copy()
for variable, value in vars_copy.items():
if variable.endswith("_dict"):
vars()[variable] = {}
elif variable.endswith("_list"):
vars()[variable] = []
print(a_dict)
print(b_dict)
print(c_list)
result:
{}
{}
[]
Maybe one of the easier kinds of implementation would be to create a list of dictionaries and lists you want to clear and later make the loop clear them all.
d = [general_feed_dict, ports_feed_dict, vulns_feed_dict, app_list]
for element in d:
element.clear()
You could also use list comprehension for that.
I'm trying to access a key in a dictionary before "declaring" it.
Similar to this:
test_dict = {'path': '/root/secret/', 'path2': test_dict['path']+'meow/'}
I am aware that I could accomplish this by doing in the next line, like:
test_dict['path2'] = test_dict['path']+'meow'
however for readability i would prefer writing all the keys in the dict for a config file.
Is this possible in Python?
Convince yourself that this is not possible. You cannot refer to an object that hasn't even been created. What you can, however, do, is use a string variable. This should do what you want relatively easily.
p = '/root/secret/'
test_dict = {'path' : p, 'path2' : os.path.join(p, 'meow')}
Also, it's good practice to use os.path.join when concatenating sub-paths together.
#cᴏʟᴅsᴘᴇᴇᴅ, I think this is more readable, imagine if OP were to add 15 paths.
p = '/root/secret/'
# initiate dict
test_dict = {}
# assign values
test_dict['path'] = p
test_dict['path2'] = os.path.join(p, 'meow')
As a total beginner I'm quite proud of this function. Although I believe there's probably an easier, more pythonic way of doing the exact same thing:
Genes = ['Gen1', 'Gen2', 'Gen3']
Mutations = ['Gen1.A', 'Gen1.B', 'Gen2.A', 'Gen3.A', 'Gen3.B', 'Gen3.C']
def RawDict(keys, values):
dictKeys = []
dictValues = []
for key in keys:
keyVal = []
for value in values:
if value.find(key) == -1:
pass
else:
keyVal.append(value)
dictKeys.append(key)
dictValues.append(keyVal)
return zip(dictKeys, dictValues)
GenDict = dict(RawDict(Genes, Mutations))
print(GenDict)
The function above is a rather overcomplicated (I think) way of putting several values (mutations) within keys (genes). However I was wondering if I could tweak this so I could get a dictionary by just doing this:
dict(GenDict, Genes, Mutations)
print(GenDict)
My struggle involves that when I use dict within the function, this won't work:
Genes = ['Gen1', 'Gen2', 'Gen3']
Mutations = ['Gen1.A', 'Gen1.B', 'Gen2.A', 'Gen3.A', 'Gen3.B', 'Gen3.C']
def fullDict(dictName, keys, values):
dictKeys = []
dictValues = []
for key in keys:
keyVal = []
for value in values:
if value.find(key) == -1:
pass
else:
keyVal.append(value)
dictKeys.append(key)
dictValues.append(keyVal)
dictName = dict(RawDict(Genes, Mutations))
fullDict(GenDict, Genes, Mutations)
print(GenDict)
The above just won't work as GenDict is not defined.
From what I understand, you want to move from this:
gen_dict = make_dictionary(genes, mutations)
to this:
make_dictionary(gen_dict, genes, mutations)
where the make_dictionary function "creates" the variable gen_dict.
Unfortunately, this isn't really how variables work. If you want to define a variable called GenDict, the way to do this is to use GenDict = .... You could do something like this:
gen_dict = {}
fill_dictionary(gen_dict, genes, mutations)
This creates a variable called gen_dict and assigns it to a new, empty dictionary. Your function would then go through and add things to that dictionary:
def fill_dictionary(d, genes, mutations):
for g in genes:
d[g] = [m for m in mutations if m.startswith(g)]
But calling a function cannot cause a new variable to appear in the caller's scope. (This is not completely true, because of globals(), but for most intents and purposes, it is.)
(By the way, there is a one-liner that will create the dictionary: dictionary = { g : [m for m in mutations if m.startswith(g+".")] for g in genes }. Search for list comprehensions and dictionary comprehensions on Google or StackOverflow -- they are amazing!)
I am assuming that you want the "Gen"s to be stored by the numerical value that it contains.
Genes = ['Gen1', 'Gen2', 'Gen3']
Mutations = ['Gen1.A', 'Gen1.B', 'Gen2.A', 'Gen3.A', 'Gen3.B', 'Gen3.C']
the_dict = {i:[] for i in Genes}
for i in Mutations:
new_val = i.split(".")
the_dict[new_val[0]].append(i)
print(the_dict)
Output:
{'Gen2': ['Gen2.A'], 'Gen3': ['Gen3.A', 'Gen3.B', 'Gen3.C'], 'Gen1': ['Gen1.A', 'Gen1.B']}
I assume you have a background in programming in some other language than Python; a language that lets you change function parameters. Well, Python does not. The problem is not with the use of dict, but rather with the fact that you're assigning to a function parameter. This will not have an effect outside the function. What you want to do is probably this:
def fullDict(keys, values):
return { key: [ value for value in values if key in value] for key in keys }
print(fullDict(Genes, Mutations))
I am using a dict in python which has the following content, basiclly it has a nested list in value set, now I want to modify the nested list.
insn = { "pop":[1,["operand1 = [esp]", "esp = esp + 4"]]}
Here is what I am doing
for k,v in insn.items():
for i, s in enumerate(v):
v[1][i] = s.replace("old", "new")
insn.update({k:v})
The code is pretty messed, I wonder if there is a simple way to do this ?
I am not entirely sure what you are trying to do here. But supposing you want to change esp or some other string within the embedded list you can do something like this:
for k, v in insn.items():
for i in range(len(v[1])):
v[1][i] = v[1][i].replace('esp', 'new_esp')
insn.update({k:v})
now you get:
>>> insn
{'pop': [1, ['operand1 = [new_esp]', 'new_esp = new_esp + 4']]}
searchindexnodes = []
searchindexnodes[1036592] = 'Apparel'
searchindexnodes[672123011] = 'Apparel'
searchindexnodes[165796011] = 'Baby'
This doesn't appear to be working. Any thoughts?
I think a better solution would be to use a dictionary. If you wanted a list with empty elements you'd be creating a list with over 100,000,000 elements which would be a huge waste of memory.
searchindexnodes = {}
searchindexnodes[1036592] = 'Apparel'
Python implements searching quickly in dictionary data structures. You could check if an element is present by doing something like
if 1036592 in searchindexnodes:
print "It's there!"
Edit to iterate through the whole list you can do something like if you want the key and value
for key, value in searchindexnodes.items():
print "{0} --> {1}".format(key,value)
otherwise what's below will loop through each key
for key in serchindexnodes:
print key
use a dictionary for that:
searchindexnodes = {}
searchindexnodes[1036592] = 'Apparel'
searchindexnodes[672123011] = 'Apparel'
searchindexnodes[165796011] = 'Baby'