I know it is easy to implement.
I want a dictionary like class, which takes a list of dictionaries in the constructor.
If you read from this dict by key, the dict-class should check the list of dictionaries and return the first value. If none contains this key KeyError should be thrown like a normal dict.
This dictionary container should be read only for my usage.
You seem to be describing collections.ChainMap, which will be in the next version of Python (3.3, expected to go final later this year). For current/earlier versions of Python, you can copy the implementation from the collections source code.
Not really answer to the question: what if you just define method that merge all dictionaries into one? Why make new class for it?
How to merge: How to merge two Python dictionaries in a single expression?
Varargs: Can a variable number of arguments be passed to a function?
You can easily implement this with this logic.
Iterate over all the dictionaries in the list.
For each dictionary, see if it has the required key by using key in value statement.
If value is found, return the value from the function.
If you have iterated over all dictionaries, and value is not found, Raise KeyError exception.
Related
the python program that i am writing calls to an api that returns this json:
Code Output
How do i access the subdetails? When i run the .keys() it only lists those three top levels. I want to be able to get specific items, e.g. "Utility"
I've tried several solutions but none parse correctly. I have tried calling the list inside the dictionary, to no avail. Originally i thought it was a dictionary inside of a dictionary, but Python thinks its a list nested into a dictionary.
Any help would be appreciated!
keys() function only returns the keys of dictionary, so it you call keys(), it will only return the three result. The "subdetails" you are referring to are the values of those keys. For key "SUMMARY" as an example, its value is a list instead of dict (note the "[" after the key). However, the list only has a single element. This is quite common in json. To retrive "Utility", all you need to do is data['SUMMARY'][0]['Utility']
Maybe to help you understand the data structure better, call the "values()" and "items()" function to see what it returns.
Since it's a dict of lists of dicts, simply use an index of 0 to access the first item of the list if there is always only one item in each list. For example, if your JSON object is stored as variable data, then the value of Utility can be accessed with data['SUMMARY'][0]['Utility'].
I've two defaultdicts I eventually want to merge, but first I need to make their keys match. According to some threads I've seen here, I can use pop() to replace keys in a dictionary. But that only updates the existing dictionary, whereas I want to create a new dictionary with the new keys. So something like:
existing_dict_one -> new_dict_one
This is what I've so far:
def split_tabs(x):
"""
Function to split tab-separated strings, used to break up the keys that are separated by tabs.
"""
return x.split('\t')
def create_dict(old_dict):
"""
Function to create a new defaultdict from an existing defaultdict, just with
different keys.
"""
new_dict = old_dict.copy() # Create a copy of old_dict to house the new keys, but with the same values.
for key, value in new_dict.iteritems():
umi = split_tabs(key)[0] # Change key to be UMI, which is the 0th index of the tab-delimited key.
# new_key = key.replace(key, umi)
new_dict[umi] = new_dict.pop(key)
return new_dict
However, I'm getting the following error
RuntimeError: dictionary changed size during iteration
and I don't know how to fix it. Does anyone know how to correct it? I'd like to use the variable "umi" as the new key.
I'd like to post the variable "key" and dictionary "old_dict" I'm using for testing this code, but it's messy and takes up a lot of space. So here's a pastebin link that contains them instead.
Note that "umi" comes from variable "key" which is separated by tabs. So I split "key" and get the first object as "umi".
Just use a dict comprehension for this:
new_dict = {split_tabs(key)[0]: value for key, value in old_dict.iteritems()}
Trying to modify a dictionary while iterating over it is not a good idea in general.
If you use .items() instead of .iteritems(), you won't have that problem, because that will just return a list that is disconnected from the dictionary. In python 3 it would be 'list(new_dict.items())`.
Also if there's any possibility that the dictionary values are mutable, you'll have to use copy.deepcopy(old_dict) instead of just old_dict.copy().
I have a python dictionary which has two keys with the same value.
mydict = {'a':'hi','b':'bye','c':'hi'}
What do I do if I want to delete just the element 'c':'hi'
I tried both del mydict['c'] and mydict.pop('c',None). Both these give me a KeyError.
First of all, there won't be a difference when you assign the same value to multiple keys. All elements in a python dict are required to have unique, immutable keys but there is no such constraint on the value. So don't worry too much about that!
This aside, both of the options you proposed behave as intended. The KeyError being thrown means that the key 'c' is not present in the dictionary. This leads me to believe that what you have shown is not in the dictionary at the time when the del or pop is called.
I want to append 'status' to the dict value indexed by 'update_fields' or add ['status'] as a value to kwargs indexed by 'update_fields' if that key isn't present.
kwargs.setdefault('update_fields', kwargs.get('update_fields', []).append('status'))
It's either this or about 3 lines of code, surely python can do better than this!
get and setdefault are essentially two methods of doing the same thing; putting them together is repeating yourself. The only difference between get and setdefault is that setdefault sets the value if the default doesn't exist. After that, they are identical semantically.
So this part:
kwargs.get('update_fields', [])
..is redundant. setdefault sets the default (and returns it, like get) if the dictionary doesn't have a value for that key yet, otherwise it just looks up the value associated with the key.
So all you need is:
kwargs.setdefault('update_fields', []).append('status')
You don't need the kwargs.get() bit, setdefault only sets the value if it's not already there, you can just write:
kwargs.setdefault('update_fields', []).append('status')
I have a Dictionary of Classes where the classes hold attributes that are lists of strings.
I made this function to find out the max number of items are in one of those lists for a particular person.
def find_max_var_amt(some_person) #pass in a patient id number, get back their max number of variables for a type of variable
max_vars=0
for key, value in patients[some_person].__dict__.items():
challenger=len(value)
if max_vars < challenger:
max_vars= challenger
return max_vars
What I want to do is rewrite it so that I do not have to use the .iteritems() function. This find_max_var_amt function works fine as is, but I am converting my code from using a dictionary to be a database using the dbm module, so typical dictionary functions will no longer work for me even though the syntax for assigning and accessing the key:value pairs will be the same. Thanks for your help!
Since dbm doesn't let you iterate over the values directly, you can iterate over the keys. To do so, you could modify your for loop to look like
for key in patients[some_person].__dict__:
value = patients[some_person].__dict__[key]
# then continue as before
I think a bigger issue, though, will be the fact that dbm only stores strings. So you won't be able to store the list directly in the database; you'll have to store a string representation of it. And that means that when you try to compute the length of the list, it won't be as simple as len(value); you'll have to develop some code to figure out the length of the list based on whatever string representation you use. It could just be as simple as len(the_string.split(',')), just be aware that you have to do it.
By the way, your existing function could be rewritten using a generator, like so:
def find_max_var_amt(some_person):
return max(len(value) for value in patients[some_person].__dict__.itervalues())
and if you did it that way, the change to iterating over keys would look like
def find_max_var_amt(some_person):
dct = patients[some_person].__dict__
return max(len(dct[key]) for key in dct)