KeyError with dict - python

I have the following
a = {'afaf178a0a3e4f91812d36a3c3289dbd': {'profile_id': 'afaf178a0a3e4f91812d36a3c3289dbd', 'cute_name': 'Watermelon'}, 'cd1800ef65ea4ac7a65effed5ed420d0': {'profile_id': 'cd1800ef65ea4ac7a65effed5ed420d0', 'cute_name': 'Peach'}, 'b673d818a57f4cdeb549c0cbe152ed51': {'profile_id': 'b673d818a57f4cdeb549c0cbe152ed51', 'cute_name': 'Papaya'}}
When trying to access it using a[0] I get a KeyError. Why is this?

Your dictionary has keys:
>>> a.keys()
['b673d818a57f4cdeb549c0cbe152ed51', 'afaf178a0a3e4f91812d36a3c3289dbd', 'cd1800ef65ea4ac7a65effed5ed420d0']
You should use one of those to access the values. Otherwise you may iterate over keys with:
for k in a.keys() :
pass # put something here
Or you may iterate over the values:
for v in a.values() :
pass # put something here
Or you may iterate over both:
for k,v in a.items() :
pass # put something here

Python raises a KeyError whenever a dict() object is requested and the key is not in the dictionary.
Using the dictionary in your post as an example:
>>> a.keys()
dict_keys(['afaf178a0a3e4f91812d36a3c3289dbd', 'cd1800ef65ea4ac7a65effed5ed420d0', 'b673d818a57f4cdeb549c0cbe152ed51'])
0 is not in the dictionary you provided, hence the KeyError.

Related

Dictionary to JSON for loop

I've tried just about everything to convert a dictionary that looks like this in Python:
d = {'name': 'Jack', 'age': 26}
I know you're able to access values like this:
d['name']
> Jack
I would like to do this in a for loop though:
for obj in d:
print(obj['name'])
Any ideas how? I've tried both json.loads and json.dumps on obj but keep getting errors like: string indices must be integers. How can I can access specific keys and get their values like the example above?
You need to access .values() of your main dict
d = {'person-1': {'name':'Jack', 'age':'26'}, 'person-2': {'name':'Idk', 'age':'23'}}
for obj in d.values():
print(obj['name'])
Jack
Idk
And .items() to get the outer key with
for key, obj in d.items():
print(key, obj['name'])
person-1 Jack
person-2 Idk

how to delete and add multiple items without iterating a dictionary in python 3.7x?

I wonder if a existing dictionary instance can add and/or delete multiple items without using iterations.
I mean something like this.
supposition:(it actually doesn't work)
D = {"key1":"value1", "key2":"value2", "key3":"value3"}
tags = ["key1","key2"]
D.pop(tags)
print(D)
{"key3":"value3"}
Thank you in advance.
If so, you could iterate a list instead of iterate the full dict:
D = {"key1":"value1", "key2":"value2", "key3":"value3"}
for i in ["key1", "key2"]:
D.pop(i)
print(D)
If you don't actually need to avoid iteration, but rather just want to do the transformation of the dictionary in an expression, rather than a statement, you could use a dictionary comprehension to create a new dictionary containing only the keys (and the associated values) that don't match your list of things to remove:
D = {key: value for key, value in D.items() if key not in tags}
Unfortunately, this doesn't modify D in place, so if you need to change the value referenced through some other variable this won't help you (and you'd need to do an explicit loop). Note that if you don't care about the values being removed, you probably should use del D[key] instead of D.pop(key).
If all you're wanting to do is show the dictionary where key from list is not present, why not just create a new dic:
D = {"key1":"value1", "key2":"value2", "key3":"value3"}
tags=["key1", "key2"]
dict = {key:value for key, value in D.items() if key not in tags}
print(dict)

Initializing a dictionary in python with a key value and no corresponding values

I was wondering if there was a way to initialize a dictionary in python with keys but no corresponding values until I set them. Such as:
Definition = {'apple': , 'ball': }
and then later i can set them:
Definition[key] = something
I only want to initialize keys but I don't know the corresponding values until I have to set them later. Basically I know what keys I want to add the values as they are found. Thanks.
Use the fromkeys function to initialize a dictionary with any default value. In your case, you will initialize with None since you don't have a default value in mind.
empty_dict = dict.fromkeys(['apple','ball'])
this will initialize empty_dict as:
empty_dict = {'apple': None, 'ball': None}
As an alternative, if you wanted to initialize the dictionary with some default value other than None, you can do:
default_value = 'xyz'
nonempty_dict = dict.fromkeys(['apple','ball'],default_value)
You could initialize them to None.
you could use a defaultdict. It will let you set dictionary values without worrying if the key already exists. If you access a key that has not been initialized yet it will return a value you specify (in the below example it will return None)
from collections import defaultdict
your_dict = defaultdict(lambda : None)
It would be good to know what your purpose is, why you want to initialize the keys in the first place. I am not sure you need to do that at all.
1) If you want to count the number of occurrences of keys, you can just do:
Definition = {}
# ...
Definition[key] = Definition.get(key, 0) + 1
2) If you want to get None (or some other value) later for keys that you did not encounter, again you can just use the get() method:
Definition.get(key) # returns None if key not stored
Definition.get(key, default_other_than_none)
3) For all other purposes, you can just use a list of the expected keys, and check if the keys found later match those.
For example, if you only want to store values for those keys:
expected_keys = ['apple', 'banana']
# ...
if key_found in expected_keys:
Definition[key_found] = value
Or if you want to make sure all expected keys were found:
assert(all(key in Definition for key in expected_keys))
You can initialize the values as empty strings and fill them in later as they are found.
dictionary = {'one':'','two':''}
dictionary['one']=1
dictionary['two']=2
Comprehension could be also convenient in this case:
# from a list
keys = ["k1", "k2"]
d = {k:None for k in keys}
# or from another dict
d1 = {"k1" : 1, "k2" : 2}
d2 = {k:None for k in d1.keys()}
d2
# {'k1': None, 'k2': None}
q = input("Apple")
w = input("Ball")
Definition = {'apple': q, 'ball': w}
Based on the clarifying comment by #user2989027, I think a good solution is the following:
definition = ['apple', 'ball']
data = {'orange':1, 'pear':2, 'apple':3, 'ball':4}
my_data = {}
for k in definition:
try:
my_data[k]=data[k]
except KeyError:
pass
print my_data
I tried not to do anything fancy here. I setup my data and an empty dictionary. I then loop through a list of strings that represent potential keys in my data dictionary. I copy each value from data to my_data, but consider the case where data may not have the key that I want.

check dictionary for doubled keys [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to raise error if duplicates keys in dictionary
I was recently generating huge dictionaries with hundreds of thousands of keys (such that noticing a bug by looking at them wasn't feasible). They were syntactically correct, yet there was a bug somewhere. It boiled down to "duplicate keys":
{'a':1, ..., 'a':2}
this code compiles fine and I could not figure out why a key has value of 2 as I expected 1. The problem is obvious now.
The question is how I can prevent that in the future. I think this is impossible within python. I used
grep "'.*'[ ]*:" myfile.py | sort | uniq -c | grep -v 1
which is not bulletproof. Any other ideas (within python, this grep is just to illustrate what I'd tried)?
EDIT: I don't want duplicate keys, just need to spot that this occurs and edit data manually
A dict cannot contain double keys. So all you need to do is execute the code and then dump the repr() of the dict.
Another option is creating the dict items as (key, value) tuples. By storing them in a list you can easily create a dict from them and then check if the len()s of the dict/list differ.
If you need to have multiple values per key you can store the values in a list using defaultdict.
>>> from collections import defaultdict
>>> data_dict = defaultdict(list)
>>> data_dict['key'].append('value')
>>> data_dict
defaultdict(<type 'list'>, {'key': ['value']})
>>> data_dict['key'].append('second_value')
>>> data_dict
defaultdict(<type 'list'>, {'key': ['value', 'second_value']})
Are you generating a Python file containing a giant dictionary? Something like:
print "{"
for lines in file:
key, _, value = lines.partition(" ")
print " '%s': '%s',"
print "}"
If so, there's not much you can do to prevent this, as you cannot easily override the construction of the builtin dict.
Instead I'd suggest you validate the data while constructing the dictionary string. You could also generate different syntax:
dict(a = '1', a = '2')
..which will generate a SyntaxError if the key is duplicated. However, these are not exactly equivalent, as dictionary keys are a lot more flexible than keyword-args (e.g {123: '...'} is valid, butdict(123 = '...')` is an error)
You could generate a function call like:
uniq_dict([('a', '...'), ('a', '...')])
Then include the function definition:
def uniq_dict(values):
thedict = {}
for k, v in values:
if k in thedict:
raise ValueError("Duplicate key %s" % k)
thedict[k] = v
return thedict
You don't say or show exactly how you're generating the dictionary display you have where the duplicate keys are appearing. But that is where the problem lies.
Instead of using something like {'a':1, ..., 'a':2} to construct the dictionary, I suggest that you use this form: dict([['a', 1], ..., ['a', 2]]) which will create one from a supplied list of [key, value] pairs. This approach will allow you to check the list of pairs for duplicates before passing it to dict() to do the actual construction of the dictionary.
Here's an example of one way to check the list of pairs for duplicates:
sample = [['a', 1], ['b', 2], ['c', 3], ['a', 2]]
def validate(pairs):
# check for duplicate key names and raise an exception if any are found
dups = []
seen = set()
for key_name,val in pairs:
if key_name in seen:
dups.append(key_name)
else:
seen.add(key_name)
if dups:
raise ValueError('Duplicate key names encountered: %r' % sorted(dups))
else:
return pairs
my_dict = dict(validate(sample))

Check for a key pattern in a dictionary in python

dict1=({"EMP$$1":1,"EMP$$2":2,"EMP$$3":3})
How to check if EMP exists in the dictionary using python
dict1.get("EMP##") ??
It's not entirely clear what you want to do.
You can loop through the keys in the dict selecting keys using the startswith() method:
>>> for key in dict1:
... if key.startswith("EMP$$"):
... print "Found",key
...
Found EMP$$1
Found EMP$$2
Found EMP$$3
You can use a list comprehension to get all the values that match:
>>> [value for key,value in dict1.items() if key.startswith("EMP$$")]
[1, 2, 3]
If you just want to know if a key matches you could use the any() function:
>>> any(key.startswith("EMP$$") for key in dict1)
True
This approach strikes me as contrary to the intent of a dictionary.
A dictionary is made up of hash keys which have had values associated with them. The benefit of this structure is that it provides very fast lookups (on the order of O(1)). By searching through the keys, you're negating that benefit.
I would suggest reorganizing your dictionary.
dict1 = {"EMP$$": {"1": 1, "2": 2, "3": 3} }
Then, finding "EMP$$" is as simple as
if "EMP$$" in dict1:
#etc...
You need to be a lot more specific with what you want to do. However, assuming the dictionary you gave:
dict1={"EMP$$1":1, "EMP$$2":2, "EMP$$3":3}
If you wanted to know if a specific key was present before trying to request it you could:
dict1.has_key('EMP$$1')
True
Returns True as dict1 has the a key EMP$$1.
You could also forget about checking for keys and rely on the default return value of dict1.get():
dict1.get('EMP$$5',0)
0
Returns 0 as default given dict1 doesn't have a key EMP$$5.
In a similar way you could also use a `try/except/ structure to catch and handle missed keys:
try:
dict1['EMP$$5']
except KeyError, e:
# Code to deal w key error
print 'Trapped key error in dict1 looking for %s' % e
The other answers to this question are also great, but we need more info to be more precise.
There's no way to match dictionary keys like this. I suggest you rethink your data structure for this problem. If this has to be extra quick you could use something like a suffix tree.
You can use in string operator that checks if item is in another string. dict1 iterator returns list of keys, so you check "EMP$$" against of each dict1.key.
dict1 = {"EMP$$1": 1, "EMP$$2": 2, "EMP$$3": 3}
print(any("EMP$$" in i for i in dict1))
# True
# testing for item that doesn't exist
print(any("AMP$$" in i for i in dict1))
# False

Categories