I've been fighting with this for quite a long time and need some help, i have some loops searching something and dynamically create dictionary object for them, for example i am scanning a store then all the buckets and then the fruits inside those buckets.
from collections import defaultdict
def tree(): return defaultdict(tree)
test = tree()
test[Store][bucket][fruits] = defaultdict(list)
test[Store][bucket][fruits].append(1)
print test
"""
desired output
{
'Store':{
'bucket1':{
'fruits':['banana', 'mango', 'apple']
}
},
'bucket2':{
'fruits':['banana', 'mango', 'apple']
}
}
}
"""
this approach throws an error and doesn't work, i also tried many other approaches like creating different dictionaries and then merging them, or creating list and then search or find and blah blah.. but i would like to find out how can i merge defaultdict objects inside each other.
can someone please help me with this.
Thanks.
Given your desired output, I don't think you need to use defaultdict(list) at all.
Rather, you can use an ordinary list:
from collections import defaultdict
def tree():
return defaultdict(tree)
test = tree()
test['Store']['bucket']['fruits'] = []
test['Store']['bucket']['fruits'].append(1)
test['Store']['bucket-13']['fruits'] = ['mango', 'apple', 'banana']
print test
However, if you do want to use defaultdict(list), the reason why it's throwing an error is because it is one level too low in your heirarchy. You want to assign it at the "bucket" level, rather then the "fruits" level:
test = tree()
test['Store']['bucket'] = defaultdict(list)
test['Store']['bucket']['fruit'].append('mango')
test['Store']['bucket']['meat'].append('chicken')
# 'fruit' and 'meat' now default to an empty list
Related
I have a code which will produce the dict as follows:
defaultdict(<type 'list'>, {u'b0116ce25cad4106becbbddfffa61a1c': [u'demo_ins1', u'2530.0'], u'1578f81703ec4bbaa1d548532c922ab9': [u'new_ins_1', u'1750.0', u'new_tenant_ins', u'2520.0']})
Code:
# inilialize necessary dict
dict_compute = defaultdict(list)
for tenants,instances in tenant_id_dict.iteritems():
for single_ins in instances:
compute_value_for_instance = ck.reports.get_total(tenant_id=tenants, service='compute', instance_id=single_ins)
dict_compute[tenants].append(single_ins)
dict_compute[tenants].append(compute_value_for_instance)
print dict_compute
Dictionary which is combination of tenant_id, Instance_name and cost.
I need to keep a relation between each other.
I need the result should be as follows:
{u'b0116ce25cad4106becbbddfffa61a1c': [u'demo_ins1' : u'2530.0']
Ie: That is for each tenant it should be displaying the instance name(demo) and cost(2530.0) as needed.
Need a better way for the same, Which one is best List or Dict.
I should be able to fetch and process if needed.
I am OK with anything(List or Dict) I just need to keep a relation.
Someone have a look and let me know the solution or suggestions.
Better try initializing a list and appending dictionary to it as below-
from collections import defaultdict
# inilialize necessary dict
dict_compute = defaultdict(list)
for tenants,instances in tenant_id_dict.iteritems():
for single_ins in instances:
compute_value_for_instance = ck.reports.get_total(tenant_id=tenants, service='compute', instance_id=single_ins)
dict_compute[tenants].append({single_ins:compute_value_for_instance})
print dict_compute
EDIT- If you need oneliner then below would work no need of using defaultdict-
dict_compute = {tenants:[{single_ins:ck.reports.get_total(tenant_id=tenants, service='compute', instance_id=single_ins)} for single_ins in instances] for tenants,instances in tenant_id_dict.iteritems()}
I want to create a nested dictionaries like the example below:
rule={}
rule["exports-rule-info-2"]["pathname"] = qtree_name
rule["exports-rule-info-2"]["security-rules"]["security-rule-info"]["read-write"]["exports-hostname-info"]["name"] = security_rules
rule["exports-rule-info-2"]["security-rules"]["security-rule-info"]["root"]["exports-hostname-info"]["name"] = security_rules
rule["exports-rule-info-2"]["security-rules"]["security-rule-info"]["sec-flavor"]["sec-flavor-info"]["flavor"] = 'sec'
You can use collections.defaultdict for this. A defaultdict is given some function used for initializing missing values. In your case, use a recursive defaultdict of defaultdict.
import collections
infinitedict = lambda: collections.defaultdict(infinitedict)
rule = infinitedict()
After putting your stuff into the defaultdict, the result will look somewhat like this (though not exactly like it, due to defaultdict slightly different representation):
{'exports-rule-info-2': {
'security-rules': {
'security-rule-info': {
'read-write': {'exports-hostname-info': {'name': 'security_rules '}},
'root': {'exports-hostname-info': {'name': 'security_rules'}},
'sec-flavor': {'sec-flavor-info': {'flavor': 'sec'}}}},
'pathname': 'qtree_name'}}
from collections import defaultdict
tree = lambda: defaultdict(tree)
rule = tree()
rule["exports-rule-info-2"]["pathname"] = qtree_name
rule["exports-rule-info-2"]["security-rules"]["security-rule-info"]["read-write"]["exports-hostname-info"]["name"] = security_rules
rule["exports-rule-info-2"]["security-rules"]["security-rule-info"]["root"]["exports-hostname-info"]["name"] = security_rules
rule["exports-rule-info-2"]["security-rules"]["security-rule-info"]["sec-flavor"]["sec-flavor-info"]["flavor"] = 'sec'
Really though, put some effort into your questions...
I am very new to python, and I have the following problem. I came up with the following solution. I am wondering whether it is "pythonic" or not. If not, what would be the best solution ?
The problem is :
I have a list of dict
each dict has at least three items
I want to find the position in the list of the dict with specific three values
This is my python example
import collections
import random
# lets build the list, for the example
dicts = []
dicts.append({'idName':'NA','idGroup':'GA','idFamily':'FA'})
dicts.append({'idName':'NA','idGroup':'GA','idFamily':'FB'})
dicts.append({'idName':'NA','idGroup':'GB','idFamily':'FA'})
dicts.append({'idName':'NA','idGroup':'GB','idFamily':'FB'})
dicts.append({'idName':'NB','idGroup':'GA','idFamily':'FA'})
dicts.append({'idName':'NB','idGroup':'GA','idFamily':'FB'})
dicts.append({'idName':'NB','idGroup':'GB','idFamily':'FA'})
dicts.append({'idName':'NB','idGroup':'GB','idFamily':'FB'})
# let's shuffle it, again for example
random.shuffle(dicts)
# now I want to have for each combination the index
# I use a recursive defaultdict definition
# because it permits creating a dict of dict
# even if it is not initialized
def tree(): return collections.defaultdict(tree)
# initiate mapping
mapping = tree()
# fill the mapping
for i,d in enumerate(dicts):
idFamily = d['idFamily']
idGroup = d['idGroup']
idName = d['idName']
mapping[idName][idGroup][idFamily] = i
# I end up with the mapping providing me with the index within
# list of dicts
Looks reasonable to me, but perhaps a little too much. You could instead do:
mapping = {
(d['idName'], d['idGroup'], d['idFamily']) : i
for i, d in enumerate(dicts)
}
Then access it with mapping['NA', 'GA', 'FA'] instead of mapping['NA']['GA']['FA']. But it really depends how you're planning to use the mapping. If you need to be able to take mapping['NA'] and use it as a dictionary then what you have is fine.
I have a list of list, s, that is the result of querying a database on Fruit, item[0] is the name of the fruit, item[1] is the whether or not the fruit has seeds, and item[2] is whether or not it's edible.
s = [['Apple','Yes','Edible'], ['Watermellon','Yes','Yes']]
As my actual list is much bigger, I would like a really easy way to reference/return these values. For example, print my_dict['Apple']['Seeds'] would yield Yes
I think my best option would be to create a dictionary, but am looking for recommendations on if this is a good method and how to do this.
I started writing some code but am not sure how to get the second set of headers in place, so my example uses an index instead.
my_dict = {t[0]:t[1:] for t in s}
print my_dict['Apple'][0]
fruit_map = {
fruit: {'Seeds': seeds, 'Edible': edible} for fruit, seeds, edible in s}
If the second set of keys never changes, it would be better to define a proper object with fields. This might seem overkill or to verbose, but there is always collections.namedtuple to help.
namedtuple creates a new class from a list of field names. That class also supports being initialized by a list. To use your example:
import collections
Fruit = collections.namedtuple('Fruit', ['name', 'seeds', 'edible'])
This way, you can easily create Fruit objects from a list:
f = Fruit('Apple', True, False)
# Or, if you already have a list with the values
params = ['Apple', True, False]
f = Fruit(*params)
print f.seed
So you can create a list of fruits in a very easy way:
s = [['Apple','Yes','Edible'], ['Watermellon','Yes','Yes']]
fruits = [Fruit(*l) for l in s]
You really need to have a dictionary indexed by a certain field, it is not much different:
s = [['Apple','Yes','Edible'], ['Watermellon','Yes','Yes']]
fruit_dict = {l[0]: Fruit(*l) for l in s}
print(fruit_dict['Apple'].seeds)
namedtuples can be very convenient when transforming lists of values into more easy to use objects (such as when reading a CSV file, which is a case very similar to what you are asking).
import copy
def list_to_dict(lst):
local = copy.copy(lst) # copied lst to local
fruit = [i.pop(0) for i in local] # get fruit names
result = {}
for i in range(len(local)):
result[fruit[i]] = local[i]
return result
This returns the dictionary you want.
Can I append to a list in a dictionary?
test = {'food' : 'apple'}
Is there a command to add 'banana' and turn it into
test = { 'food': ['apple','banana'] }
Thank you
No, since it isn't a list in the first place.
test['food'] = [test['food'], 'banana']
You need to create a dict where the values are lists:
test = {'food' : ['apple']}
test['food'].append('banana')
The simplest solution would just be to just make the value of your hash a list, that may contain just one element. Then for example, you might have something like this:
test = {'food' : ['apple']}
test['food'].append('banana')
I'd recommend using a defaultdict in this case, it's pretty straightforward to deal with dictionaries of lists, since then you don't need two separate cases every time you modify an entry:
import collections
test = collections.defaultdict(list)
test['food'].append('apple')
test['food'].append('banana')
print test
# defaultdict(<type 'list'>, {'food': ['apple', 'banana']})