Key error in dictionary. How to make Python print my dictionary? - python

In my homework, this question is asking me to make a function where Python should create dictionary of how many words that start with a certain letter in the long string is symmetrical. Symmetrical means the word starts with one letter and ends in the same letter. I do not need help with the algorithm for this. I definitely know I have it right, but however I just need to fix this Key error that I cannot figure out. I wrote d[word[0]] += 1, which is to add 1 to the frequency of words that start with that particular letter.
The output should look like this (using the string I provided below):
{'d': 1, 'i': 3, 't': 1}
t = '''The sun did not shine
it was too wet to play
so we sat in the house
all that cold cold wet day
I sat there with Sally
we sat there we two
and I said how I wish
we had something to do'''
def symmetry(text):
from collections import defaultdict
d = {}
wordList = text.split()
for word in wordList:
if word[0] == word[-1]:
d[word[0]] += 1
print(d)
print(symmetry(t))

You're trying to increase the value of an entry which has yet to be made resulting in the KeyError. You could use get() for when there is no entry for a key yet; a default of 0 will be made (or any other value you choose). With this method, you would not need defaultdict (although very useful in certain cases).
def symmetry(text):
d = {}
wordList = text.split()
for word in wordList:
key = word[0]
if key == word[-1]:
d[key] = d.get(key, 0) + 1
print(d)
print(symmetry(t))
Sample Output
{'I': 3, 'd': 1, 't': 1}

You never actually use collections.defaultdict, although you import it. Initialize d as defaultdict(int), instead of as {}, and you're good to go.
def symmetry(text):
from collections import defaultdict
d = defaultdict(int)
wordList = text.split()
for word in wordList:
if word[0] == word[-1]:
d[word[0]] += 1
print(d)
print(symmetry(t))
Results in:
defaultdict(<class 'int'>, {'I': 3, 't': 1, 'd': 1})

Related

How to update an empty python dictionary by iterating over a word yielding like: {'letter in word':position of letter}? [duplicate]

This question already has answers here:
Assigning keys to a dictionary from a string
(3 answers)
Closed 4 years ago.
I am trying to convert this string into a dictionary such that it produces a key-value pair where the Key is the alphabet and the Value is its corresponding position in the word: example
word = 'jazz'
word_dict = {'j':[0],'a':[1],'z':[2,3]}
This is what I am trying to do:
word = 'jazz'
word_dict = {}
for key, value in enumerate(word):
dict_word = {value:key}
print(dict_word)
The code above yeilds:
{'j': 0}
{'a': 1}
{'z': 2}
{'z': 3}
I am kind of stuck here and don't know how to proceed further so that I can update these outputs generated from the loop into a dictionary as mentioned above. I am kind of new to this so any help will be appreciated.
Thank you.
You can use a defaultdict:
from collections import defaultdict
word = 'jazz'
word_dict = defaultdict(list)
for idx, chr in enumerate(word):
word_dict[chr].append(idx)
print(word_dict)
Output:
defaultdict(list, {'j': [0], 'a': [1], 'z': [2, 3]})
The resulting defaultdict acts exactly like a real dict, but if you need it as a dict for some reason, you can call dict(word_dict). However, everywhere where a dict will work, a defaultdict will work as it's a subclass.
Is this what you are looking for?
word = 'jazz'
word_dict = {}
for key_as_value, value_as_key in enumerate(word):
if value_as_key in word_dict:
word_dict[value_as_key].append(key_as_value)
else:
word_dict[value_as_key] = [key_as_value]
print(word_dict)
# below is the output
{'j': [0], 'a': [1], 'z': [2, 3]}
Is this working what you are looking for ?
Please check this code.
word = 'jazz'
word_dict = {}
for key, value in enumerate(word):
dict_word = {value:key}
word_dict.update(dict_word)
print(dict_word)
print (word_dict)

Python key error in function

I have a function that should return the number of words that contain each vowel (all lowercase), but I keep getting a key error. I'd appreciate any help in figuring it out. Thank you.
def vowelUseDict(t):
'''computes and returns a dictionary with the number of words in t containing each vowel
'''
vowelsUsed = {}
strList = t.split()
newList = []
vowels ='aeiou'
for v in vowels:
for strs in strList:
if v in strs and strs not in newList:
newList.append(strs)
vowelsUsed[v] = 1
if v in strs and strs in newList:
vowelsUsed[v] += 1
return vowelsUsed
text = 'like a vision she dances across the porch as the radio plays'
print(vowelUseDict(text))
#{'e': 5, 'u': 0, 'o': 4, 'a': 6, 'i': 3}
from collections import Counter
def vowelUseDict(t):
vowels = 'aeiou'
cnt = sum(map(Counter, t.split()), Counter())
return {k: cnt[k] if k in cnt else 0 for k in vowels}
That's because newList keeps the words from the previous vowels. Once you reach "like" for "i", it already exists since it was added for "e". This means that it tries to add to the value for key "i" in vowelsUsed, which doesn't exist (it would get added the first time a word is found that hasn't been added for another vowel).
Since (judging by the last line) you want every vowel to be in the resulting dict, you can just create the dict with all the vowels as keys and the values as zero, and you don't even have to check if a key exists. Just increase the value by one if the word contains the vowel.
The resulting code would be something like this:
def vowelUseDict(t):
'''computes and returns a dictionary with the number of words in t containing each vowel
'''
strList = t.split()
vowels ='aeiou'
vowelsUsed = {v: 0 for v in vowels}
for v in vowels:
for strs in strList:
if v in strs:
vowelsUsed[v] += 1
return vowelsUsed
text = 'like a vision she dances across the porch as the radio plays'
print(vowelUseDict(text))
#{'e': 5, 'u': 0, 'o': 4, 'a': 6, 'i': 3}
Roy Orbison singing for the lonely; hey, that's me and I want you only

How does dict.setdefault() count the number of characters?

I got this code from the book Automate the boring stuff with Python, and I don't understand how the setdefault() method counts the number of unique characters.
Code:
message = 'It was a bright cold day in April, and the clocks were striking thirteen.'
count = {}
for character in message:
count.setdefault(character, 0)
count[character] = count[character] + 1
print(count)
According to the book, the setdefault() method searches for the key in the dictionary and if not found updates the dictionary, if found does nothing.
But I don't understand the counting behaviour of setdefault and how it is done?
Output:
{' ': 13, ',': 1, '.': 1, 'A': 1, 'I': 1, 'a': 4, 'c': 3, 'b': 1, 'e': 5, 'd': 3, 'g': 2,
'i': 6, 'h': 3, 'k': 2, 'l': 3, 'o': 2, 'n': 4, 'p': 1, 's': 3, 'r': 5, 't': 6, 'w': 2, 'y': 1}
Please explain this to me.
In your example setdefault() is equivalent to this code...
if character not in count:
count[character] = 0
This is a nicer way (arguably) to do the same thing:
from collections import defaultdict
message = 'It was a bright cold day in April, and the clocks were striking thirteen.'
count = defaultdict(int)
for character in message:
count[character] = count[character] + 1
print(count)
It works because the default int is 0.
An even nicer way is as follows:
from collections import Counter
print(Counter(
'It was a bright cold day in April, '
'and the clocks were striking thirteen.'))
It would be better to use defaultdict in at least this case.
from collections import defaultdict
count = defaultdict(int)
for character in message:
count[character] += 1
A defaultdict is constructed with a no argument function which creates an instance of whatever default value should be. If a key is not there then this function provides a value for it and inserts the key, value in the dictionary for you. Since int() returns 0 it is initialized correctly in this case. If you wanted it initialized to some other value, n, then you would do something like
count = defaultdict(lambda : n)
I am using the same textbook and I had the same problem. The answers provided are more sophisticated than the example in question, so they don't actually address the issue: the question above is - how does the code understand that it should count the number of occurrences. It turns out, it doesn't really "count". It just keeps changing the values, until it stops. So here is how I explained it to myself after a long and painful research:
message='It was a bright,\
cold day in April,\
and the clocks were \
striking thirteen.'
count={} # "count" is set as an empty dictionary, which we want to fill out
for character in message: # for each character, do the following:
count.setdefault(character,0) # if the character is not there,
# take it from the message above
# and set it in the dictionary
# so the new key is a letter (e.g. 'a') and value is 0
# (zero is the only value that we can set by default
# otherwise we would gladly set it to 1 (to start with the 1st occurrence))
# but if the character already exists - this line will do nothing! (this is pointed out in the same book, page 110)
# the next time it finds the same character
# - which means, its second occurrence -
# it won't change the key (letter)
# But we still want to change the value, so we write the following line:
count[character]=count[character]+1 # and this line will change the value e.g. increase it by 1
# because "count[character]",
# is a number, e.g. count['a'] is 1 after its first occurrence
# This is not an "n=n+1" line that we remember from while loops
# it doesn't mean "increase the number by 1
# and do the same operation from the start"
# it simply changes the value (which is an integer) ,
# which we are currently processing in our dictionary, by 1
# to summarize: we want the code to go through the characters
# and only react to the first occurence of each of them; so
# the setdefault does exactly that; it ignores the values;
# second, we want the code to increase the value by 1
# each time it encounters the same key;
# So in short:
# setdefault deals with the key only if it is new (first occurence)
# and the value can be set to change at each occurence,
# by a simple statement with a "+" operator
# the most important thing to understand here is that
# setdefault ignores the values, so to speak,
# and only takes keys, and even them only if they are newly introduced.
print(count) # prints the whole obtained dictionary
answer by #egon is very good and it answers the doubts raised here. I just modified the code little bit and hope it will be easy to understand now.
message = 'naga'
count = {}
for character in message:
count.setdefault(character,0)
print(count)
count[character] = count[character] + 1
print(count)
print(count)
and the output will be as follows
{'n': 0} # first key and value set in count
{'n': 1} # set to this value when count[character] = count[character] + 1 is executed.
{'n': 1, 'a': 0} # so on
{'n': 1, 'a': 1}
{'g': 0, 'n': 1, 'a': 1}
{'g': 1, 'n': 1, 'a': 1}
{'g': 1, 'n': 1, 'a': 1}
{'g': 1, 'n': 1, 'a': 2}
{'g': 1, 'n': 1, 'a': 2}
message = 'It was a bright cold day in April, and the clocks were striking thirteen.'
count = {} #This is an empty dictionary. We will add key-value pairs to this dictionary with the help of the following lines of code (The for-loop and its code block).
for character in message: #The loop will run for the number of single characters (Each letter & each space between the words are characters) in the string assigned to 'message'.
#That means the loop will run for 73 times.
#In each iteration of the loop, 'character' will be set to the current character of the string for the running iteration.
#That means the loop will start with 'I' and end with '.'(period). 'I' is the current character of the first iteration and '.' is the current character of the last iteration of the for-loop.
count.setdefault(character, 0) #If the character assigned to 'character' is not in the 'count' dictionary, then the character will be added to the dictionary as a key with its value being set to 0.
count[character] = count[character] + 1 #The value of the key (character added as key) of 'count' in the running iteration of the loop is incremented by one.
#As a result of a key's value being incremented, we can track how many times a particular character in the string was iterated.
#^It's because the existing value of the existing key will be incremented by 1 for the number of times the particular character is iterated.
#The accuracy of exactly how many times a value should be incremented is ensured because already existing keys in the dictionary aren't updated with new values by set.default(), as it does so only if the key is missing in the dictionary.
print(count) #Prints out the dictionary with all the key-value pairs added.
#The key and its value in each key-value pair represent a specific character from the string assigned to 'message' and the number of times it's found in the string, respectively.

create a dictionary for letters

I have been trying to build a function to get letter frequencies from a string and store them in a dictionary.
I have done something like that :
s="today the weather was really nice"
def get_letter_freq(s):
for letter in(s):
x=letter.split()
f=dict()
for each_letter in x:
if f.has_key(x):
f[x]+=1
else:
f[x]=1
print f
Could you help me put things into order and find my mistakes?
Why I get an error that my 'f' is not defined?
In your code, your first for loop, where you have your letter.split() statement seems useless. Why you want to split a single character, you get in your loop?
Secondly, you have defined your f = dict() inside your function and
using it ouside. It will not be visible outside.
Third, your should not use f.has_key. Just do, key in my_dict to
check for availability of key in dict.
And at last, you can pass your dictionary as parameter to your
function. Then modify it there, and finally return it. (Although you can also do it without passing the dict in your function. just create a new one there, and return it).
So, in your code, almost everything is fine. You just need to remove your first for loop in function, and move f = dict() outside the function, before invoking it. And pass it as a paramter.
Way 1:
So, you can rather try the following modified code of yours: -
def get_letter_freq(my_dict, s):
for letter in s:
if letter in my_dict:
my_dict[letter] += 1
else:
my_dict[letter] = 1
return my_dict
my_dict = dict()
my_str = "today the weather was really nice"
print get_letter_freq(my_dict, my_str)
Way 2: -
Alternatively, you can also use a pre-defined library function Counter from collections, which does exactly what you want.
WAY 3: -
As suggested by #thebjorn in comment, you can also use defaultdict, which will make your task easier, in that, you won't have to check for the availability of key in dictionary before adding it. The count will automatically default to 0: -
from collections import defaultdict
def get_letter_freq(s):
my_dict = defaultdict(int)
for letter in s:
my_dict[letter] += 1
return my_dict
my_str = "today the weather was really nice"
print list(get_letter_freq(my_str).items())
Besides that indentation error your program has many other problems, like:
s = "today the weather was really nice"
def get_letter_freq(s):
f = dict()
for each_letter in s: #you can directly iterate over a string, so no need of split()
if each_letter in f: #has_key() has been deprecated
f[each_letter]+=1
else:
f[each_letter]=1
return f #better return the output from function
print get_letter_freq(s)
By the way collections.Counter() is good for this purpose:
In [61]: from collections import Counter
In [62]: strs = "today the weather was really nice"
In [63]: Counter(strs)
Out[63]: Counter({' ': 5, 'e': 5, 'a': 4, 't': 3, 'h': 2, 'l': 2, 'r': 2, 'w': 2, 'y': 2, 'c': 1, 'd': 1, 'i': 1, 'o': 1, 'n': 1, 's': 1})
f is defined inside get_letter_freq, you can't access it from outside.
Your function should return the constructed dictionary.
You should actually call the function.
What do you expect from splitting a single letter? Just leave that part out, and you don't need the inner loop.
print f needs to be indented, if it has to be part of get_letter_freq.
& f does not exist outside get_letter_freq. Hence the error.
import string
s="today the weather was really nice"
print dict([ ( letter, s.count(letter)) for letter in string.lowercase[:25]])
If case sensitivity is important use s.lower().count(letter) instead.

Understanding .get() method in Python [duplicate]

This question already has answers here:
Why dict.get(key) instead of dict[key]?
(14 answers)
Closed 4 years ago.
sentence = "The quick brown fox jumped over the lazy dog."
characters = {}
for character in sentence:
characters[character] = characters.get(character, 0) + 1
print(characters)
I don't understand what characters.get(character, 0) + 1 is doing, rest all seems pretty straightforward.
The get method of a dict (like for example characters) works just like indexing the dict, except that, if the key is missing, instead of raising a KeyError it returns the default value (if you call .get with just one argument, the key, the default value is None).
So an equivalent Python function (where calling myget(d, k, v) is just like d.get(k, v) might be:
def myget(d, k, v=None):
try: return d[k]
except KeyError: return v
The sample code in your question is clearly trying to count the number of occurrences of each character: if it already has a count for a given character, get returns it (so it's just incremented by one), else get returns 0 (so the incrementing correctly gives 1 at a character's first occurrence in the string).
To understand what is going on, let's take one letter(repeated more than once) in the sentence string and follow what happens when it goes through the loop.
Remember that we start off with an empty characters dictionary
characters = {}
I will pick the letter 'e'. Let's pass the character 'e' (found in the word The) for the first time through the loop. I will assume it's the first character to go through the loop and I'll substitute the variables with their values:
for 'e' in "The quick brown fox jumped over the lazy dog.":
{}['e'] = {}.get('e', 0) + 1
characters.get('e', 0) tells python to look for the key 'e' in the dictionary. If it's not found it returns 0. Since this is the first time 'e' is passed through the loop, the character 'e' is not found in the dictionary yet, so the get method returns 0. This 0 value is then added to the 1 (present in the characters[character] = characters.get(character,0) + 1 equation).
After completion of the first loop using the 'e' character, we now have an entry in the dictionary like this: {'e': 1}
The dictionary is now:
characters = {'e': 1}
Now, let's pass the second 'e' (found in the word jumped) through the same loop. I'll assume it's the second character to go through the loop and I'll update the variables with their new values:
for 'e' in "The quick brown fox jumped over the lazy dog.":
{'e': 1}['e'] = {'e': 1}.get('e', 0) + 1
Here the get method finds a key entry for 'e' and finds its value which is 1.
We add this to the other 1 in characters.get(character, 0) + 1 and get 2 as result.
When we apply this in the characters[character] = characters.get(character, 0) + 1 equation:
characters['e'] = 2
It should be clear that the last equation assigns a new value 2 to the already present 'e' key.
Therefore the dictionary is now:
characters = {'e': 2}
Start here http://docs.python.org/tutorial/datastructures.html#dictionaries
Then here http://docs.python.org/library/stdtypes.html#mapping-types-dict
Then here http://docs.python.org/library/stdtypes.html#dict.get
characters.get( key, default )
key is a character
default is 0
If the character is in the dictionary, characters, you get the dictionary object.
If not, you get 0.
Syntax:
get(key[, default])
Return the value for key if key is in the dictionary, else default. If default is not given, it defaults to None, so that this method never raises a KeyError.
If d is a dictionary, then d.get(k, v) means, give me the value of k in d, unless k isn't there, in which case give me v. It's being used here to get the current count of the character, which should start at 0 if the character hasn't been encountered before.
I see this is a fairly old question, but this looks like one of those times when something's been written without knowledge of a language feature. The collections library exists to fulfill these purposes.
from collections import Counter
letter_counter = Counter()
for letter in 'The quick brown fox jumps over the lazy dog':
letter_counter[letter] += 1
>>> letter_counter
Counter({' ': 8, 'o': 4, 'e': 3, 'h': 2, 'r': 2, 'u': 2, 'T': 1, 'a': 1, 'c': 1, 'b': 1, 'd': 1, 'g': 1, 'f': 1, 'i': 1, 'k': 1, 'j': 1, 'm': 1, 'l': 1, 'n': 1, 'q': 1, 'p': 1, 's': 1, 't': 1, 'w': 1, 'v': 1, 'y': 1, 'x': 1, 'z': 1})
In this example the spaces are being counted, obviously, but whether or not you want those filtered is up to you.
As for the dict.get(a_key, default_value), there have been several answers to this particular question -- this method returns the value of the key, or the default_value you supply. The first argument is the key you're looking for, the second argument is the default for when that key is not present.

Categories