Reputation: 145
In the following code that I wrote, n = 4, and so there are five if statements, so if I would like to increase n to be, say 10, then there will be a lot of if's. Therefore my question: how can I replace all the if statements with something more elegant?
n, p = 4, .5 # number of trials, probability of each trial
s = np.random.binomial(n, p, 100)
# result of flipping a coin 10 times, tested 1000 times.
d = {"0" : 0, "1" : 0, "2" : 0, "3" : 0, "4" : 0 }
for i in s:
if i == 0:
d["0"] += 1
if i == 1:
d["1"] += 1
if i == 2:
d["2"] += 1
if i == 3:
d["3"] += 1
if i == 4:
d["4"] += 1
I tried using nested for loops,
for i in s:
for j in range(0,5):
if i == j:
d["j"] += 1
But i get this error:
d["j"] += 1
KeyError: 'j'
Upvotes: 2
Views: 316
Reputation: 12689
You can try something like this without importing any external module:
In one line
import numpy as np
n, p = 4, .5 # number of trials, probability of each trial
s = np.random.binomial(n, p, 100)
# result of flipping a coin 10 times, tested 1000 times.
d = {"0" : 0, "1" : 0, "2" : 0, "3" : 0, "4" : 0 }
[d.__setitem__(str(i),d[str(i)]+1) for i in s for j in range(0, 5) if str(i) in d]
print(d)
output: (as it is random so can be anything)
{'1': 22, '3': 23, '0': 3, '4': 6, '2': 46}
Detailed solution:
for i in s:
for j in range(0, 5):
if str(i) in d:
d[str(i)]+=1
print(d)
output:
{'4': 6, '0': 6, '3': 29, '1': 25, '2': 34}
Upvotes: 1
Reputation: 152840
You could use collections.Counter
with a comprehension:
from collections import Counter
Counter(str(i) for i in s)
Counter
works here because you're incrementing by one. However if you want it more general you could also use collections.defaultdict
:
from collections import defaultdict
dd = defaultdict(int) # use int as factory - this will generate 0s for missing entries
for i in s:
dd[str(i)] += 1 # but you could also use += 2 or whatever here.
or if you want it as plain dictionary, wrap it inside a dict
call, for example:
dict(Counter(str(i) for i in s))
Both avoid KeyError
s when the key isn't present yet and you avoid the double loop.
As a side note: If you want plain dicts you could also use dict.get
:
d = {} # empty dict
for i in d:
d[str(i)] = d.get(str(i), 0) + 1
However Counter
and defaultdict
behave almost like plain dictionaries so there's almost no need for this last one, because it is (probably) slower and in my opinion less readable.
Upvotes: 7
Reputation: 6149
Alternatively to Miket25's answer, you can actually use numbers as dictionary keys, like:
d = {0: 0, 1: 0, 2: 0, 3: 0, 4: 0 }
for i in s:
# 0 <= i < 5 is the same as looking through and checking
# all values 0-4 but more efficient and cleaner.
if 0 <= i < 5:
d[i] += 1
Upvotes: 6
Reputation: 1913
You need to convert the integer to a string in the loop.
for i in s:
for j in range(0,5):
if i == j:
d[str(j)] += 1
Upvotes: 7