Python - Updating dictionary values after a .count() function while iterating - python

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

Related

Fill a column with multiple conditions from other columns

Is it possible to fill a column according to other conditions?
I made a false algorithm:
if (df.b == 3) & (df.c == 0) & (df.a == None):
df['d'] == 0
else:
df['b']
and I tried
import pandas
df = pandas.DataFrame([{'a': None, 'b': 3, 'c': 0},
{'a': "string", 'b': 0, 'c': 3},
{'a': "string", 'b': 3, 'c': 0}])
df['d'] = [0 if ((df.b == 3) & (df.c == 0) & (df.a == None)) else pass]
SyntaxError: invalid syntax
I need
df = pandas.DataFrame([{'a': None, 'b': 3, 'c': 0, 'd': 0},
{'a': "string", 'b': 0, 'c': 3, 'd': 0},
{'a': "string", 'b': 3, 'c': 0, 'd': 3}])
IIUC, Series.mask
df['d'] = df['b'].mask(df['b'].eq(3) & df['c'].eq(0) & df['a'].isnull(), 0)
print (df)
a b c d
0 None 3 0 0
1 string 0 3 0
2 string 3 0 3
you can use np.where and isnullto get where a is None.
import numpy as np
df['d'] = np.where((df.b == 3) & (df.c == 0) & (df.a.isnull()), 0, df['b'])
print (df)
a b c d
0 None 3 0 0
1 string 0 3 0
2 string 3 0 3
df['d'] = df['b'].mask(df['b'].eq(3) & df['c'].eq(0) & df['a'].isnull(), 0)
print (df)
a b c d
0 None 3 0 0
1 string 0 3 0
2 string 3 0 3

Pseudo-random generation of python list containing binary values with run-length and frequency constraints

I want to pseudo-randomly create a list with 48 entries -- 24 zeros and 24 ones -- where the same value never occurs three times in a row. I have the following code:
import random
l = list()
for i in range(48):
if len(l) < 2:
l.append(random.choice([0,1]))
else:
if l[i-1] == l[i-2]:
if l[i-1] == 0:
l.append(1)
else:
l.append(0)
else:
l.append(random.choice([0,1]))
But sometimes the count of 0s and 1s is uneven.
Getting uniformity without using rejection is tricky.
The rejection approach is straightforward, something like
def brute(n):
seq = [0]*n+[1]*n
while True:
random.shuffle(seq)
if not any(len(set(seq[i:i+3])) == 1 for i in range(len(seq)-2)):
break
return seq
which will be very slow at large n but is reliable.
There's probably a slick way to take a non-rejection sample where it's almost trivial, but I couldn't see it and instead I fell back on methods which work generally. You can make sure that you're uniformly sampling the space if at each branch point, you weight the options by the number of successful sequences you generate if you take that choice.
So, we use dynamic programming to make a utility which counts the number of possible sequences, and extend to the general case where we have (#zeroes, #ones) bits left, and then use this to provide the weights for our draws. (We could actually refactor this into one function but I think they're clearer if they're separate, even if it introduces some duplication.)
from functools import lru_cache
import random
def take_one(bits_left, last_bits, choice):
# Convenience function to subtract a bit from the bits_left
# bit count and shift the last bits seen.
bits_left = list(bits_left)
bits_left[choice] -= 1
return tuple(bits_left), (last_bits + (choice,))[-2:]
#lru_cache(None)
def count_seq(bits_left, last_bits=()):
if bits_left == (0, 0):
return 1 # hooray, we made a valid sequence!
if min(bits_left) < 0:
return 0 # silly input
if 0 in bits_left and max(bits_left) > 2:
return 0 # short-circuit if we know it won't work
tot = 0
for choice in [0, 1]:
if list(last_bits).count(choice) == 2:
continue # can't have 3 consec.
new_bits_left, new_last_bits = take_one(bits_left, last_bits, choice)
tot += count_seq(new_bits_left, new_last_bits)
return tot
def draw_bits(n):
bits_left = [n, n]
bits_drawn = []
for bit in range(2*n):
weights = []
for choice in [0, 1]:
if bits_drawn[-2:].count(choice) == 2:
weights.append(0) # forbid this case
continue
new_bits_left, new_last_bits = take_one(bits_left, tuple(bits_drawn[-2:]), choice)
weights.append(count_seq(new_bits_left, new_last_bits))
bit_drawn = random.choices([0, 1], weights=weights)[0]
bits_left[bit_drawn] -= 1
bits_drawn.append(bit_drawn)
return bits_drawn
First, we can see how many such valid sequences there are:
In [1130]: [count_seq((i,i)) for i in range(12)]
Out[1130]: [1, 2, 6, 14, 34, 84, 208, 518, 1296, 3254, 8196, 20700]
which is A177790 at the OEIS, named
Number of paths from (0,0) to (n,n) avoiding 3 or more consecutive east steps and 3 or more consecutive north steps.
which if you think about it is exactly what we have, treating a 0 as an east step and a 1 as a north step.
Our random draws look good:
In [1145]: draw_bits(4)
Out[1145]: [0, 1, 1, 0, 1, 0, 0, 1]
In [1146]: draw_bits(10)
Out[1146]: [0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0]
and are quite uniform:
In [1151]: Counter(tuple(draw_bits(4)) for i in range(10**6))
Out[1151]:
Counter({(0, 0, 1, 0, 1, 0, 1, 1): 29219,
(1, 0, 1, 0, 0, 1, 0, 1): 29287,
(1, 1, 0, 0, 1, 0, 1, 0): 29311,
(1, 0, 1, 0, 1, 0, 1, 0): 29371,
(1, 0, 1, 0, 1, 1, 0, 0): 29279,
(0, 1, 0, 1, 0, 0, 1, 1): 29232,
(0, 1, 0, 1, 1, 0, 1, 0): 29824,
(0, 1, 1, 0, 0, 1, 1, 0): 29165,
(0, 1, 1, 0, 1, 0, 0, 1): 29467,
(1, 1, 0, 0, 1, 1, 0, 0): 29454,
(1, 0, 1, 1, 0, 0, 1, 0): 29338,
(0, 0, 1, 1, 0, 0, 1, 1): 29486,
(0, 1, 1, 0, 1, 1, 0, 0): 29592,
(0, 0, 1, 1, 0, 1, 0, 1): 29716,
(1, 1, 0, 1, 0, 0, 1, 0): 29500,
(1, 0, 0, 1, 0, 1, 0, 1): 29396,
(1, 0, 1, 0, 0, 1, 1, 0): 29390,
(0, 1, 1, 0, 0, 1, 0, 1): 29394,
(0, 1, 1, 0, 1, 0, 1, 0): 29213,
(0, 1, 0, 0, 1, 0, 1, 1): 29139,
(0, 1, 0, 1, 0, 1, 1, 0): 29413,
(1, 0, 0, 1, 0, 1, 1, 0): 29502,
(0, 1, 0, 1, 0, 1, 0, 1): 29750,
(0, 1, 0, 0, 1, 1, 0, 1): 29097,
(0, 0, 1, 1, 0, 1, 1, 0): 29377,
(1, 1, 0, 0, 1, 0, 0, 1): 29480,
(1, 1, 0, 1, 0, 1, 0, 0): 29533,
(1, 0, 0, 1, 0, 0, 1, 1): 29500,
(0, 1, 0, 1, 1, 0, 0, 1): 29528,
(1, 0, 1, 0, 1, 0, 0, 1): 29511,
(1, 0, 0, 1, 1, 0, 0, 1): 29599,
(1, 0, 1, 1, 0, 1, 0, 0): 29167,
(1, 0, 0, 1, 1, 0, 1, 0): 29594,
(0, 0, 1, 0, 1, 1, 0, 1): 29176})
Coverage is also correct, in that we can recover the A177790 counts by randomly sampling (and with some luck):
In [1164]: [len(set(tuple(draw_bits(i)) for _ in range(20000))) for i in range(9)]
Out[1164]: [1, 2, 6, 14, 34, 84, 208, 518, 1296]
Here's a reasonably efficient solution that gives you fairly random output that obeys the constraints, although it doesn't cover the full solution space.
We can ensure that the number of zeroes and ones are equal by ensuring that the number of single zeros equals the number of single ones, and the number of pairs of zeros equals the number of pairs of ones. In a perfectly random output list we'd expect the number of singles to be roughly double the number of pairs. This algorithm makes that exact: each list has 12 singles of each type, and 6 pairs.
Those run lengths are stored in a list named runlengths. On each round, we shuffle that list to get the sequence of run lengths for the zeros, and shuffle it again to get the sequence of run lengths for the ones. We then fill the output list by alternating between runs of zeroes and ones.
To check that the lists are correct we use the sum function. If there are equal numbers of zeroes and ones the sum of a list is 24.
from random import seed, shuffle
seed(42)
runlengths = [1] * 12 + [2] * 6
bits = [[0], [1]]
for i in range(10):
shuffle(runlengths)
a = runlengths[:]
shuffle(runlengths)
b = runlengths[:]
shuffle(bits)
out = []
for u, v in zip(a, b):
out.extend(bits[0] * u)
out.extend(bits[1] * v)
print(i, ':', *out, ':', sum(out))
output
0 : 0 0 1 0 0 1 1 0 1 0 1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 1 0 1 1 0 1 0 1 1 0 0 1 0 0 1 0 1 1 0 1 1 0 1 : 24
1 : 0 1 0 0 1 0 1 1 0 0 1 0 1 0 1 0 0 1 0 1 1 0 0 1 0 1 1 0 1 0 1 1 0 0 1 0 1 0 1 1 0 0 1 0 1 1 0 1 : 24
2 : 0 0 1 1 0 0 1 0 0 1 0 1 0 1 1 0 1 0 1 1 0 0 1 0 1 1 0 1 1 0 1 0 1 0 1 0 1 0 1 0 0 1 0 1 1 0 0 1 : 24
3 : 0 0 1 0 1 1 0 0 1 1 0 1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 1 0 0 1 0 1 1 0 1 1 0 0 1 1 0 1 0 1 0 1 0 1 : 24
4 : 1 1 0 0 1 0 1 0 1 0 1 1 0 1 1 0 1 0 1 1 0 1 0 1 0 0 1 0 1 0 0 1 0 1 0 0 1 1 0 0 1 0 1 1 0 0 1 0 : 24
5 : 1 1 0 1 0 1 0 1 1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 1 1 0 1 0 1 0 0 1 1 0 0 1 1 0 0 1 0 1 0 1 0 1 0 0 : 24
6 : 1 0 1 0 0 1 0 0 1 0 0 1 1 0 0 1 1 0 1 0 0 1 1 0 1 1 0 1 1 0 1 0 1 0 1 0 1 0 0 1 0 1 1 0 1 0 1 0 : 24
7 : 0 1 0 0 1 1 0 1 0 0 1 0 1 0 1 0 1 0 1 0 1 1 0 1 1 0 1 0 0 1 0 0 1 0 1 1 0 1 1 0 1 1 0 0 1 0 0 1 : 24
8 : 0 0 1 1 0 1 0 1 0 0 1 0 0 1 0 1 0 1 1 0 1 1 0 1 0 1 0 0 1 0 0 1 0 1 1 0 1 0 1 1 0 1 1 0 0 1 0 1 : 24
9 : 1 0 1 1 0 1 1 0 1 1 0 1 0 0 1 0 1 0 1 1 0 0 1 0 0 1 0 0 1 0 1 0 0 1 0 0 1 0 1 0 1 1 0 1 0 1 1 0 : 24
Here is a simple code that obeys your constraints:
import random
def run():
counts = [24, 24]
last = [random.choice([0, 1]), random.choice([0, 1])]
counts[last[0]] -= 1
counts[last[1]] -= 1
while sum(counts) > 0:
can_pick_ones = sum(last[-2:]) < 2 and counts[1] > 0.33 * (48 - len(last))
can_pick_zeros = sum(last[-2:]) > 0 and counts[0] > 0.33 * (48 - len(last))
if can_pick_ones and can_pick_zeros:
value = random.choice([0, 1])
elif can_pick_ones:
value = 1
elif can_pick_zeros:
value = 0
counts[value] -= 1
last.append(value)
return last
for i in range(4):
r = run()
print(sum(r), r)
Output
24 [1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0]
24 [0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1]
24 [0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1]
24 [1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0]
Rationale
At each step of the while loop you can either choose 1, choose 0 or both. You can choose:
1 if the last two elements are not one and the counts of 1 is larger than 1/3 the amount of remaining slots: sum(last[-2:]) < 2 and counts[1] > 0.33 * (48 - len(last))
0 if the last two elements are not 0 and the counts of 0 is larger than 1/3 the amount of remaining slots: sum(last[-2:]) > 0 and counts[0] > 0.33 * (48 - len(last))
Both if you can choose 1 or 0
The sum of the two last elements can be 0, 1 or 2, if equals 0 it means that the last two elements were 0 so you can only pick 0 if sum(last[-2:]) > 0. If equals 2 it means that the last two elements where 1, so you can only pick 1 if sum(last[-2:]) < 2. Finally you need to check that the amount of elements of both 1 and 0 are at least a third of the remaining positions to assign, otherwise you are going to be forced to create a run of three consecutive equal elements.

Dictionary of punctuation counts for list of strings

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})

counting individual characters in a large list of passwords without killing loop

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']

Convert every character in a String to a Dictionary Key

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 ||
>>>

Categories