Suppose i have a string "abcdefghijklmnopqrstuvwxyz"and i want to initialize dictionary keys with those values.
alphabet = 'abcdefghijklmnopqrstuvwxyz'
alphabetDict = dict()
for char in alphabet:
alphabetDict[char] = 0
Is there a better way of doing that?
You can use dict.fromkeys() method -
>>> s = 'abcdefghijklmnopqrstuvwxyz'
>>> alphaDict = dict.fromkeys(s,0)
>>> alphaDict
{'m': 0, 'p': 0, 'i': 0, 'n': 0, 'd': 0, 'w': 0, 'k': 0, 'y': 0, 's': 0, 'b': 0, 'h': 0, 't': 0, 'u': 0, 'q': 0, 'g': 0, 'l': 0, 'e': 0, 'a': 0, 'j': 0, 'c': 0, 'o': 0, 'f': 0, 'v': 0, 'x': 0, 'z': 0, 'r': 0}
From documentation -
fromkeys(seq[, value])
Create a new dictionary with keys from seq and values set to value.
fromkeys() is a class method that returns a new dictionary. value defaults to None.
Please note, you should not use this if value is something mutable like list or another dict , etc. As the value is only evaluted once when you call the method fromkeys() , and all keys point to the same object.
You can use this for immutable types as value like int, str , etc.
Also, you do not need to specify the s or alphabet string, you can instead use string.ascii_lowercase . Example -
>>> import string
>>> alphaDict = dict.fromkeys(string.ascii_lowercase,0)
>>> alphaDict
{'m': 0, 'p': 0, 'i': 0, 'n': 0, 'd': 0, 'w': 0, 'k': 0, 'y': 0, 's': 0, 'b': 0, 'h': 0, 't': 0, 'u': 0, 'q': 0, 'g': 0, 'l': 0, 'e': 0, 'a': 0, 'j': 0, 'c': 0, 'o': 0, 'f': 0, 'v': 0, 'x': 0, 'z': 0, 'r': 0}
You can use dictionary comprehensions in Python.
alphabetDict = {char: 0 for char in alphabet}
Dictionaries (Python Docs)
There is a minor difference between this answer and Anand's above. Dict comprehensions evaluate the value for every key, while fromkeys only does it once. If you're using things like ints, this poses no problem. However, if you do
d = {key: [] for key in <some set>}
d[3].append(5)
print(d[2])
gives you
[]
and you have distinct lists, while
d = dict.fromkeys(<some set>, [])
d[3].append(5)
print(d[2])
gives you
[5]
will map all the keys to the same list.
Yes, you can do that in one line using dictionary comprehensions.
In [1]: alphabet = 'abcdefghijklmnopqrstuvwxyz'
In [2]: {x:0 for x in alphabet} # dictionary comprehension
Out[2]:
{'a': 0,
'b': 0,
'c': 0,
'd': 0,
'e': 0,
'f': 0,
'g': 0,
'h': 0,
'i': 0,
'j': 0,
'k': 0,
'l': 0,
'm': 0,
'n': 0,
'o': 0,
'p': 0,
'q': 0,
'r': 0,
's': 0,
't': 0,
'u': 0,
'v': 0,
'w': 0,
'x': 0,
'y': 0,
'z': 0}
Tried with another approach.
dict(zip(alphabets, '0'*len(alphabets)))
If you need a dictionary with different values instead of a constant value, you may create one like below with the use of random module:
>>> import random
>>> alphabet = 'abcdefghijklmnopqrstuvwxyz'
>>> my_dict = dict([ (ch, random.randint(1,len(alphabet)) ) for ch in alphabet ] )
>>> my_dict
{'a': 17, 'b': 15, 'c': 3, 'd': 5, 'e': 5, 'f': 13, 'g': 7, 'h': 1, 'i': 3, 'j': 12, 'k': 11, 'l': 7, 'm': 8, 'n': 23, 'o': 15, 'p': 7, 'q': 9, 'r': 19, 's': 17, 't': 22, 'u': 20, 'v': 24, 'w': 26, 'x': 14, 'y': 7, 'z': 24}
>>>
I creates dictionaries like above when I need a dictionary with random values for testing purposes.
Another way to create a dictionary with each char of a text with character count.
>>> char_count = lambda text, char: text.count(char)
>>> text = "Genesis 1 - 1 In the beginning God created the heavens and the earth. 2 Now the earth was formless and desolate, and there was darkness upon the surface of the watery deep, and God's active force was moving about over the surface of the waters."
>>> my_dict = dict( [ ( char, char_count(text, char) ) for char in text ] )
>>> my_dict
{'G': 3, 'e': 32, 'n': 13, 's': 15, 'i': 5, ' ': 45, '1': 2, '-': 1, 'I': 1, 't': 17, 'h': 12, 'b': 2, 'g': 3, 'o': 12, 'd': 10, 'c': 5, 'r': 12, 'a': 19, 'v': 4, '.': 2, '2': 1, 'N': 1, 'w': 6, 'f': 6, 'm': 2, 'l': 2, ',': 2, 'k': 1, 'u': 4, 'p': 2, 'y': 1, "'": 1}
Explanation:
1. lambda function counts number of occurrences of a characters.
2. Call lambda function for each character in text to get the count of that particular character.
Note: You may improve this code to avoid duplicate calls for repeated characters.
Using dictionary comprehension may be easier than all above:
{ char:(text.count(char)) for char in text }
In order to avoid duplication as mentioned by #Robert Ranjan , we do it this way
>>> import string
>>> char_count = lambda text, char: text.count(char)
>>> allAscii = list(string.printable)
>>> # alphabet = 'abcdefghijklmnopqrstuvwxyz'
>>> text = "Genesis 1 - 1 In the beginning God created the heavens and the earth. 2 Now the earth was formless and desolate, and * # there was darkness upon the surface of the watery deep, and God's active force was moving about over the surface of the waters."
>>> # my_dict = dict( [ ( char, char_count(text, char) ) for char in alphabet]
>>> my_dict = dict( [ ( char, char_count(text, char) ) for char in allAscii]
>>> for eachKey in my_dict:
print(repr(eachKey), ': ', my_dict[eachKey], ' ', end=' || ')
'0' : 0 || '1' : 2 || '2' : 1 || '3' : 0 || '4' : 0 || '5' : 0 || '6' : 0 || '7' : 0 || '8' : 0 || '9' : 0 || 'a' : 19 || 'b' : 2 || 'c' : 5 || 'd' : 10 || 'e' : 32 || 'f' : 6 || 'g' : 3 || 'h' : 12 || 'i' : 5 || 'j' : 0 || 'k' : 1 || 'l' : 2 || 'm' : 2 || 'n' : 13 || 'o' : 12 || 'p' : 2 || 'q' : 0 || 'r' : 12 || 's' : 15 || 't' : 17 || 'u' : 4 || 'v' : 4 || 'w' : 6 || 'x' : 0 || 'y' : 1 || 'z' : 0 || 'A' : 0 || 'B' : 0 || 'C' : 0 || 'D' : 0 || 'E' : 0 || 'F' : 0 || 'G' : 3 || 'H' : 0 || 'I' : 1 || 'J' : 0 || 'K' : 0 || 'L' : 0 || 'M' : 0 || 'N' : 1 || 'O' : 0 || 'P' : 0 || 'Q' : 0 || 'R' : 0 || 'S' : 0 || 'T' : 0 || 'U' : 0 || 'V' : 0 || 'W' : 0 || 'X' : 0 || 'Y' : 0 || 'Z' : 0 || '!' : 0 || '"' : 0 || '#' : 0 || '$' : 0 || '%' : 0 || '&' : 0 || "'" : 1 || '(' : 0 || ')' : 0 || '*' : 1 || '+' : 0 || ',' : 2 || '-' : 1 || '.' : 2 || '/' : 0 || ':' : 0 || ';' : 0 || '<' : 0 || '=' : 0 || '>' : 0 || '?' : 0 || '#' : 1 || '[' : 0 || '\\' : 0 || ']' : 0 || '^' : 0 || '_' : 0 || '`' : 0 || '{' : 0 || '|' : 0 || '}' : 0 || '~' : 0 || ' ' : 47 || '\t' : 0 || '\n' : 0 || '\r' : 0 || '\x0b' : 0 || '\x0c' : 0 ||
>>>
Related
What would I write to iterate over a string and for each letter, if that letter is in a given dictionary (as a key), then add that key's value to an empty list?
For example the string 'cat', I want to search a given dictionary for c, a, and t. Then for each value of each letter, add them to a new list that is a sum of points (values).
I keep getting: TypeError: 'NoneType' object is not iterable
Here's what I have so far:
user_word = cat
values_dict = {'A' : 1, 'E' : 1, 'I' : 1, 'O' : 1, 'U' : 1, 'L' : 1,\
'N' : 1, 'N' : 1, 'S' : 1, 'T' : 1, 'R' : 1,\
'D' : 2, 'G' : 2, 'B' : 3, 'C' : 3, 'M' : 3, 'P' : 3,\
'F' : 4, 'H' : 4, 'V' : 4, 'W' : 4, 'Y' : 4,\
'K' : 5, 'J' : 8, 'X' : 8, 'Q' : 10, 'Z' : 10,}
def get_word_value(user_word, values_dict):
word_pts = 0
for letter in user_word.upper():
for key, value in values_dict.items:
for letter in range(value):
word_pts = word_pts + values_dict[letter]
print(word_pts, 'TEST GOOD')
return word_pts
# expected result is 5 (3+1+1= 5)
Here's a one liner:
sum([values_dict[letter] for letter in user_word.upper()])
I'd suggest you to use
sum([values_dict.get(letter, 0) for letter in user_word.upper()])
This will avoid error if the key is not found.
The TypeError: 'NoneType' object is not iterable is due to line
for key, value in values_dict.items:.
dict.items is a function and not an iterable. To access the actual values, use the parenthesis to iter over the key and values: for key, value in values_dict.items():
Here is your code corrected :
user_word = "cat"
values_dict = {'A' : 1, 'E' : 1, 'I' : 1, 'O' : 1, 'U' : 1, 'L': 1,
'N' : 1, 'S' : 1, 'T' : 1, 'R' : 1,
'D' : 2, 'G' : 2, 'B' : 3, 'C' : 3, 'M' : 3, 'P': 3,
'F' : 4, 'H' : 4, 'V' : 4, 'W' : 4, 'Y' : 4,
'K' : 5, 'J' : 8, 'X' : 8, 'Q' : 10, 'Z' : 10}
def get_word_value(user_word, values_dict):
word_pts = 0
for letter in user_word.upper():
for key, value in zip(values_dict.keys(), values_dict.values()):
if letter == key:
word_pts += value
print('Word pts : {} , TEST GOOD'.format(word_pts))
return word_pts
You can use the operator itemgetter(). It‘s faster than a list comprehension:
from operator import itemgetter
d = {'A': 1, 'T': 1, 'C': 3, 'E': 1}
w = 'cat'
sum(itemgetter(*w.upper())(d))
# 5
user_input = raw_input("Enter Your Word: ")
user_input = user_input.upper()
wordArray = list(user_input)
values_dict = {'A' : 1, 'E' : 1, 'I' : 1, 'O' : 1, 'U' : 1, 'L' : 1,
'N' : 1, 'N' : 1, 'S' : 1, 'T' : 1, 'R' : 1,
'D' : 2, 'G' : 2, 'B' : 3, 'C' : 3, 'M' : 3, 'P' : 3,
'F' : 4, 'H' : 4, 'V' : 4, 'W' : 4, 'Y' : 4,
'K' : 5, 'J' : 8, 'X' : 8, 'Q' : 10, 'Z' : 10,}
def get_word_value(wordArray, values_dict):
word_pts = 0
for letter in wordArray:
word_pts = word_pts + values_dict[letter]
print "Word Points: %d, Test Good." % word_pts
get_word_value(wordArray, values_dict)
How can I use dict comprehension to build a dictionary of punctuation counts for a list of strings? I was able to do it for a single string like this:
import string
test_string = "1990; and 1989', \ '1975/97', '618-907 CE"
counts = {p:test_string.count(p) for p in string.punctuation}
Edit: For anyone who may want this in the future, here's Patrick Artner's answer copied from below, with a very small modification to keep only punctuation counts:
# return punctuation Counter dict for string/list/pd.Series
import string
from collections import Counter
from itertools import chain
def count_punctuation(str_series_or_list):
c = Counter(chain(*str_series_or_list))
unwanted = set(c) - set(string.punctuation)
for unwanted_key in unwanted: del c[unwanted_key]
return c
Why count yourself?
import string
from collections import Counter
test_string = "1990; and 1989', \ '1975/97', '618-907 CE"
c = Counter(test_string) # counts all occurences
for p in string.punctuation: # prints the one in string.punctuation
print(p , c[p]) # access like dictionary (its a subclass of dict)
print(c)
Output:
! 0
" 0
# 0
$ 0
% 0
& 0
' 4
( 0
) 0
* 0
+ 0
, 2
- 1
. 0
/ 1
: 0
; 1
< 0
= 0
> 0
? 0
# 0
[ 0
\ 1
] 0
^ 0
_ 0
` 0
{ 0
| 0
} 0
~ 0
Counter({'9': 7, ' ': 6, '1': 4, "'": 4, '7': 3, '0': 2, '8': 2, ',': 2, ';': 1, 'a': 1, 'n': 1, 'd': 1, '\\': 1, '5': 1, '/': 1, '6': 1, '-': 1, 'C': 1, 'E': 1})
Counter is dictionary-like: see https://docs.python.org/2/library/collections.html#collections.Counter
Edit: multiple strings in a list:
import string
from collections import Counter
from itertools import chain
test_strings = [ "1990; and 1989', \ '1975/97', '618-907 CE" , "someone... or no one? that's the question!", "No I am not!"]
c = Counter(chain(*test_strings))
for p in string.punctuation:
print(p , c[p])
print(c)
Output: (removed 0-Entries)
! 2
' 5
, 2
- 1
. 3
/ 1
; 1
? 1
\ 1
Counter({' ': 15, 'o': 8, '9': 7, 'n': 6, "'": 5, 'e': 5, 't': 5, '1': 4, 'a': 3, '7': 3, 's': 3, '.': 3, '0': 2, '8': 2, ',': 2, 'm': 2, 'h': 2, '!': 2, ';': 1, 'd': 1, '\\': 1, '5': 1, '/': 1, '6': 1, '-': 1, 'C': 1, 'E': 1, 'r': 1, '?': 1, 'q': 1, 'u': 1, 'i': 1, 'N': 1, 'I': 1})
I'm trying to get a count on, for example, how many a's are in a massive list of passwords out of curiosity. but i think when i'm trying to add a count for a character it's killing the loop that is going through all the characters.
#Examine passwords.txt
file = open('passwords.txt','r')
a = 0
b = 0
c = 0
d = 0
e = 0
f = 0
g = 0
h = 0
i = 0
j = 0
k = 0
l = 0
m = 0
n = 0
o = 0
p = 0
q = 0
r = 0
s = 0
t = 0
u = 0
v = 0
w = 0
x = 0
y = 0
z = 0
with open('passwords.txt','r') as fileobj:
for line in fileobj:
for char in line:
if char == a:
a += 1
elif char == b:
b += 1
print(a)
print(b)
print(c)
print(d)
print(e)
print(f)
You should use a dictionary (or a list which has an order) to store how many counts of each letter there are. This is much better than using 26 one letter variables which is ridiculous!
To create a dictionary, you can use a dictionary-comprehension with str.count on the entire contents of the file.
with open('passwords.txt','r') as fileobj:
text = fileobj.read()
letterCounts = {c: text.count(c) for c in "abcdefghijklmnopqrstuvwxyz"}
which would give letterCounts as something like:
{'s': 0, 'a': 4, 'o': 0, 'i': 0, 'm': 0, 'k': 0, 'q': 0, 'y': 0, 'c': 1, 'j': 0, 'b': 4, 'g': 0, 'd': 1, 'h': 0, 'e': 0, 'f': 0, 'u': 0, 'n': 0, 'w': 0, 't': 0, 'x': 0, 'p': 0, 'l': 0, 'r': 0, 'z': 0, 'v': 0}
from collections import Counter
with open('passwords.txt','r') as fileobj:
counts = Counter()
for line in fileobj:
counts.update(line)
counts is a Counter keeping track of the counts of all the characters that appear in the file. YOu would access the number of as with counts['a']
I am thinking of something with collections
s = 'Hello Mr. Rogers, how are you this fine Tuesday?'
import collections
c = collections.Counter(s)
As a result I have
Counter({' ': 8,
',': 1,
'.': 1,
'?': 1,
'H': 1,
'M': 1,
'R': 1,
'T': 1,
'a': 2,
'd': 1,
'e': 5,
'f': 1,
'g': 1,
'h': 2,
'i': 2,
'l': 2,
'n': 1,
'o': 4,
'r': 3,
's': 3,
't': 1,
'u': 2,
'w': 1,
'y': 2})
If I try sum I got syntax problem
print sum(1 for i in c if i.isupper())
File "<ipython-input-21-66a7538534ee>", line 4
print sum(1 for i in c if i.isupper())
^
SyntaxError: invalid syntax
How should I count only upper or lower from the counter?
You lack the () in your generator expresion:
sum((1 for x in c if x.isupper()))
4
EDIT: As #Błotosmętek sugest, you lack the () in your print, i guess you are using python3, you should use print()
You can try something like this:
import collections
s = 'Hello Mr. Rogers, how are you this fine Tuesday?'
c = collections.Counter([ch for ch in s if ch.isupper()])
# Change to ch.islower() if you need lower case
# c = collections.Counter([ch for ch in s if ch.islower()])
print(c)
I'm having a problem with counting letters in a string and then updating this value to a dictionary.
I am iterating through a dictionary of alphabet letters and using the .count() function at each pair to compare to a sentence.
The count is working and returns the number you would expect (in this case xval), however this is not updating the dictionary when I use dic[k] = xval.
Infuriatingly simple. Please offer some advice if you can.
import string
type = ("cat sat on the mat").lower()
dic = dict.fromkeys(string.ascii_lowercase, 0)
print(dic)
for k, v in dic.items():
xval = type.count(k)
print(xval)
dic[k] = xval
print ("%s: %s" % (k, v))
And here is the output for completion. Many thanks.
{'m': 0, 'l': 0, 'h': 0, 'f': 0, 'd': 0, 'x': 0, 'i': 0, 's': 0, 'r': 0, 'u': 0, 'z': 0, 't': 0, 'c': 0, 'a': 0, 'q': 0, 'p': 0, 'j': 0, 'n': 0, 'g': 0, 'w': 0, 'o': 0, 'e': 0, 'k': 0, 'b': 0, 'v': 0, 'y': 0}
0
f: 0
0
q: 0
0
r: 0
1
m: 0
1
c: 0
3
a: 0
0
u: 0
0
g: 0
1
e: 0
0
d: 0
0
v: 0
1
h: 0
0
y: 0
0
k: 0
4
t: 0
0
i: 0
1
o: 0
0
w: 0
0
b: 0
1
s: 0
0
l: 0
0
j: 0
0
x: 0
0
z: 0
1
n: 0
0
p: 0
Process finished with exit code 0
You are printing k and v which do not reflect the updated dictionary.
import string
type = ("cat sat on the mat").lower()
dic = dict.fromkeys(string.ascii_lowercase, 0)
print(dic)
for k in dic:
xval = type.count(k)
print(xval)
dic[k] = xval
print k, ":", dic[k]
outputs
{'a': 0, 'c': 0, 'b': 0, 'e': 0, 'd': 0, 'g': 0, 'f': 0, 'i': 0, 'h': 0, 'k': 0, 'j': 0, 'm': 0, 'l': 0, 'o': 0, 'n': 0, 'q': 0, 'p': 0, 's': 0, 'r': 0, 'u': 0, 't': 0, 'w': 0, 'v': 0, 'y': 0, 'x': 0, 'z': 0}
3
a : 3
1
c : 1
0
b : 0
1
e : 1
0
d : 0
0
g : 0
0
f : 0
0
i : 0
1
h : 1
0
k : 0
0
j : 0
1
m : 1
0
l : 0
1
o : 1
1
n : 1
0
q : 0
0
p : 0
1
s : 1
0
r : 0
0
u : 0
4
t : 4
0
w : 0
0
v : 0
0
y : 0
0
x : 0
0
z : 0