Program optimisation and working of dictionary in adding key value pairs - python

this is my program on counting the number of vowels
'''Program to count number of vowels'''
str=input("Enter a string\n")
a=0
e=0
i=0
o=0
u=0
for x in str:
if x=='a':
a=a+1
continue
if x=='e':
e=e+1
continue
if x=='i':
i=i+1
continue
if x=='o':
o=o+1
continue
if x=='u':
u=u+1
continue
count={}
if a>0:
count['a']=a
if e>0:
count['e']=e
if i>0:
count['i']=i
if o>0:
count['o']=o
if u>0:
count['u']=u
print(count)
How can I improve the initial loop for comparison along with the process of filling the dictionary.
While running the program several times I have obtained the following output:
>>>
Enter a string
abcdefgh
{'e': 1, 'a': 1}
>>> ================================ RESTART ================================
>>>
Enter a string
abcdefghijklmnopqrstuvwxyz
{'u': 1, 'a': 1, 'o': 1, 'e': 1, 'i': 1}
>>> ================================ RESTART ================================
>>>
Enter a string
abcdeabcdeiopiop
{'a': 2, 'o': 2, 'i': 2, 'e': 2}
From this I could not figure out how exactly are the key value pairs being added to the dictionary count against my expectation of:
Case 1:
{'a':1, 'e':1}
Case 2:
{'a':1, 'e':1, 'i':1, 'o':1, 'u':1}
Case 3:
{'a':2, 'e':2, 'i':2, 'o':2}
Any help is appreciated.

>>> import collections
>>> s = "aacbed"
>>> count = collections.Counter(c for c in s if c in "aeiou")
>>> count
Counter({'a': 2, 'e': 1})
Or - if you really need to maintain insertion order:
>>> s = 'debcaa'
>>> count=collections.OrderedDict((c, s.count(c)) for c in s if c in "aeiou")
>>> count
OrderedDict([('e', 1), ('a', 2)])
Finally if you want lexicographic ordering, you can either turn your dict/counter/ OrderedDict into a list of tuples:
>>> sorted(count.items())
[('a', 2), ('e', 1)]
and if you want a lexicographically OrderedDict:
>>> sorted_count = collections.OrderedDict(sorted(count.items()))
>>> sorted_count
OrderedDict([('a', 2), ('e', 1)])

A more Pythonic way to do what you want is:
'''Program to count number of vowels'''
s = input("Enter a string\n")
count = {v: s.count(v) for v in "aeiou" if s.count(v) > 0}
print(count)
You shouldn't use str as a variable name, as that is the name of the built-in string type.

Just put a=0 e=0 i=0 o=0 u=0 inside a dictionary like that:
myDict = {'a':0, 'e':0, 'i':0, 'o':0, 'u':0}
for x in string:
myDict[x] += 1
print myDict
If the value is not one of the following then a raise of KeyError will come up.
So you can do something like that:
myDict = {'a': 0, 'e': 0, 'i': 0, 'o': 0, 'u': 0}
for x in string:
try:
myDict[x] += 1
except KeyError:
continue
print myDict
Note: I've changed the name str to string
You can also see a very good solution by #Amber here

Related

Python: How can I sort the values in a dictionary according to size and display the 3 largest values?

For example: I have the following string s = "I do not understand this". I would now like to display the 3 most frequently occurring characters in the string s, without using "sorted" or packages.
I have the following code:
s = "I do not understand this"
d = {}
spaces = " "
for b in s:
if b not in spaces:
if b not in d:
d[b] = 1
else:
d[b] = d[b]+ 1
But I don't know how to go on.
You can create your own list with (key, value) tuples where you'll define the order. You'll then be able to convert this list back to a sorted dictionary:
s = "I do not understand this"
d = {}
for b in s:
if b != " ":
d[b] = d.get(b, 0) + 1
# the sorting part:
most_occurring_letters = [list(d.items())[0]] # list with first key/value of your dict
# going through all other keys
for b in list(d)[1:]:
for i, (letter, count) in enumerate(most_occurring_letters):
if d[b] >= d[letter]:
most_occurring_letters.insert(i, (b, d[b]))
break
print(most_occurring_letters[:3]) # the 3 most occurring elements
Output:
[('t', 3), ('n', 3), ('d', 3)]
Convert to dict to get a sorted dictionary:
print(dict(most_occurring_letters))
Output:
{'t': 3, 'n': 3, 'd': 3, 's': 2, 'o': 2, 'i': 1, 'h': 1, 'a': 1, 'r': 1, 'e': 1, 'u': 1, 'I': 1}

identify unique letters and corresponding count in input_string

input_string=mississippi
output_dict={letters=[i,s,p,m],count=[4,4,2,1]}
Remove duplicate entries from input_string and count those duplicate values and display in descending order.
actual following code remove duplicate entry but how to count the duplicate values
def mock(input_string):
a=list(input_string)
list1=[]
for i in a:
if i not in list1:
list1.append(i)
print(list1)
mock("radffffghhh")
d={}
for i in input_string:
d[i]=d.get(i,0)+1
sort dict by values in reverse
sorted(d.items(), key=lambda kv: kv[1],reverse=True)#[('i', 4), ('s', 4), ('p', 2), ('m', 1)]
Using groupby
from itertools import groupby
{k:len(list(v)) for k,v in groupby(sorted(input_string))}
Using Counter
from collections import Counter
Counter(input_string)
Edit to do this without Counter:
def char_counter(string):
count = {}
for s in string:
if s in count:
count[s] += 1
else:
count[s] = 1
return count
char_counter(input_string)
output for "mississippi":
>>> char_counter(input_string)
{'i': 4, 'm': 1, 'p': 2, 's': 4}
collections has a package for this mentioned above called Counter. So taking your string:
from collections import Counter
input_string='mississippi'
Counter(input_string) # call Counter on your input string
#alternative to just call counter on the string:
Counter('mississippi')
output for both:
>>> Counter(input_string)
Counter({'i': 4, 'm': 1, 'p': 2, 's': 4})
>>> Counter('mississippi')
Counter({'i': 4, 'm': 1, 'p': 2, 's': 4})

Nested for-loops and dictionaries in finding value occurrence in string

I've been tasked with creating a dictionary whose keys are elements found in a string and whose values count the number of occurrences per value.
Ex.
"abracadabra" → {'r': 2, 'd': 1, 'c': 1, 'b': 2, 'a': 5}
I have the for-loop logic behind it here:
xs = "hshhsf"
xsUnique = "".join(set(xs))
occurrences = []
freq = []
counter = 0
for i in range(len(xsUnique)):
for x in range(len(xs)):
if xsUnique[i] == xs[x]:
occurrences.append(xs[x])
counter += 1
freq.append(counter)
freq.append(xsUnique[i])
counter = 0
This does exactly what I want it to do, except with lists instead of dictionaries. How can I make it so counter becomes a value, and xsUnique[i] becomes a key in a new dictionary?
The easiest way is to use a Counter:
>>> from collections import Counter
>>> Counter("abracadabra")
Counter({'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
If you can't use a Python library, you can use dict.get with a default value of 0 to make your own counter:
s="abracadabra"
count={}
for c in s:
count[c] = count.get(c, 0)+1
>>> count
{'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1}
Or, you can use dict.fromkeys() to set all the values in a counter to zero and then use that:
>>> counter={}.fromkeys(s, 0)
>>> counter
{'a': 0, 'r': 0, 'b': 0, 'c': 0, 'd': 0}
>>> for c in s:
... counter[c]+=1
...
>>> counter
{'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1}
If you truly want the least Pythonic, i.e., what you might do in C, you would maybe do:
create a list for all possible ascii values set to 0
loop over the string and count characters that are present
Print non zero values
Example:
ascii_counts=[0]*255
s="abracadabra"
for c in s:
ascii_counts[ord(c)]+=1
for i, e in enumerate(ascii_counts):
if e:
print chr(i), e
Prints:
a 5
b 2
c 1
d 1
r 2
That does not scale to use with Unicode, however, since you would need more than 1 million list entries...
You can use zip function to convert your list to dictionary :
>>> dict(zip(freq[1::2],freq[0::2]))
{'h': 3, 's': 2, 'f': 1}
But as more pythonic and pretty optimized way I suggest to use collections.Counter
>>> from collections import Counter
>>> Counter("hshhsf")
Counter({'h': 3, 's': 2, 'f': 1})
And as you said you don't want to import any module you can use a dictionary using dict.setdefault method and a simple loop:
>>> d={}
>>> for i in xs:
... d[i]=d.setdefault(i,0)+1
...
>>> d
{'h': 3, 's': 2, 'f': 1}
I'm guessing theres a learning reason as to why your using two forloops?
Anyway heres a few different solutions:
# Method 1
xs = 'hshhsf'
xsUnique = ''.join(set(xs))
freq1 = {}
for i in range(len(xsUnique)):
for x in range(len(xs)):
if xsUnique[i] == xs[x]:
if xs[x] in freq1:
freq1[xs[x]] += 1
else:
freq1[xs[x]] = 1 # Introduce a new key, value pair
# Method 2
# Or use a defaultdict that auto initialize new values in a dictionary
# https://docs.python.org/2/library/collections.html#collections.defaultdict
from collections import defaultdict
freq2 = defaultdict(int) # new values initialize to 0
for i in range(len(xsUnique)):
for x in range(len(xs)):
if xsUnique[i] == xs[x]:
# no need to check if xs[x] is in the dict because
# defaultdict(int) will set any new key to zero, then
# preforms it's operation.
freq2[xs[x]] += 1
# I don't understand why your using 2 forloops though
# Method 3
string = 'hshhsf' # the variable name `xs` confuses me, sorry
freq3 = defaultdict(int)
for char in string:
freq3[char] += 1
# Method 4
freq4 = {}
for char in string:
if char in freq4:
freq4[char] += 1
else:
freq4[char] = 1
print 'freq1: %r\n' % freq1
print 'freq2: %r\n' % freq2
print 'freq3: %r\n' % freq3
print 'freq4: %r\n' % freq4
print '\nDo all the dictionaries equal each other as they stand?'
print 'Answer: %r\n\n' % (freq1 == freq2 and freq1 == freq3 and freq1 == freq4)
# convert the defaultdict's to a dict for consistency
freq2 = dict(freq2)
freq3 = dict(freq3)
print 'freq1: %r' % freq2
print 'freq2: %r' % freq2
print 'freq3: %r' % freq3
print 'freq4: %r' % freq4
Output
freq1: {'h': 3, 's': 2, 'f': 1}
freq2: defaultdict(<type 'int'>, {'h': 3, 's': 2, 'f': 1})
freq3: defaultdict(<type 'int'>, {'h': 3, 's': 2, 'f': 1})
freq4: {'h': 3, 's': 2, 'f': 1}
Do all the dictionaries equal each other as they stand?
Answer: True
freq1: {'h': 3, 's': 2, 'f': 1}
freq2: {'h': 3, 's': 2, 'f': 1}
freq3: {'h': 3, 's': 2, 'f': 1}
freq4: {'h': 3, 's': 2, 'f': 1}
[Finished in 0.1s]
Or like dawg stated, use Counter from the collections standard library
counter docs
https://docs.python.org/2/library/collections.html#collections.Counter
defaultdict docs
https://docs.python.org/2/library/collections.html#collections.defaultdict
collections library docs
https://docs.python.org/2/library/collections.html

Python Counting Vowels

I have started on a program to count vowels and have seemed to be getting nowhere. I need to count vowels from a string and then display the vowels. I need to do this by storing the number of occurrences in variables. Like this :
a = 0
b = 0
....
then print the lowest.
Current code (its not that much ):
string = str(input("please input a string: "))
edit= ''.join(string)
print(edit)
I have tried a number of methods just by my self and don't seem to get anywhere.
You could use a dictionary comprehension:
>>> example = 'this is an example string'
>>> vowel_counts = {c: example.count(c) for c in 'aeoiu'}
>>> vowel_counts
{'i': 2, 'o': 0, 'e': 5, 'u': 0, 'a': 2}
Then finding the minimum, maximum etc. is trivial.
>>> a="hello how are you"
>>> vowel_count = dict.fromkeys('aeiou',0)
>>> vowel_count
{'a': 0, 'i': 0, 'e': 0, 'u': 0, 'o': 0}
>>> for x in 'aeiou':
... vowel_count[x]=a.count(x)
...
>>> vowel_count
{'a': 1, 'i': 0, 'e': 2, 'u': 1, 'o': 3}
now from here you can print low nd max
You can use dictionary for this problem. Iterate over each character and if the character is a vowel, put it in dictionary with count 0 and increment its count by 1, and for every next occurrence keep incrementing the count.
>>> string = str(input("please input a string: "))
please input a string: 'Hello how are you'
>>> dt={} # initialize dictionary
>>> for i in string: # iterate over each character
... if i in ['a','e','i','o','u']: # if vowel
... dt.setdefault(i,0) # at first occurrence set count to 0
... dt[i]+=1 # increment count by 1
...
>>> dt
{'a': 1, 'u': 1, 'e': 2, 'o': 3}
word = input('Enter Your word : ')
vowel = 'aeiou'
vowel_counter = {}
for char in word:
if char in vowel:
vowel_counter[char] = vowel_counter.setdefault(char,0)+1
sorted_result = sorted(vowel_counter.items(), reverse=True,key=lambda x : x[1])
for key,val in sorted_result:
print(key,val)

How to convert dictionary into string

I'm trying to use the solution provided here
Instead of getting a dictionary, how can I get a string with the same output i.e. character followed by the number of occurrences
Example:d2m2e2s3
To convert from the dict to the string in the format you want:
''.join('{}{}'.format(key, val) for key, val in adict.items())
if you want them alphabetically ordered by key:
''.join('{}{}'.format(key, val) for key, val in sorted(adict.items()))
Is this what you are looking for?
#!/usr/bin/python
dt={'d': 2, 'f': 2, 'g': 2, 'q': 5, 'w': 3}
st=""
for key,val in dt.iteritems():
st = st + key + str(val)
print st
output: q5w3d2g2f2
Or this?
#!/usr/bin/python
dt={'d': 2, 'f': 2, 'g': 2, 'q': 5, 'w': 3}
dt=sorted(dt.iteritems())
st=""
for key,val in dt:
st = st + key + str(val)
print st
output: d2f2g2q5w3
Example with join:
#!/usr/bin/python
adict=dt={'d': 2, 'f': 2, 'g': 2, 'q': 5, 'w': 3}
' '.join('{0}{1}'.format(key, val) for key, val in sorted(adict.items()))
output: 'd2 f2 g2 q5 w3'
>>> result = {'d': 2, 'f': 2, 'g': 2, 'q': 5, 'w': 3}
>>> ''.join('%s%d' % (k,v) for k,v in result.iteritems())
'q5w3d2g2f2'
or if you want them alphabetically...
>>> ''.join('%s%d' % (k,v) for k,v in sorted(result.iteritems()))
'd2f2g2q5w3'
or if you want them in increasing order of count...
>>> ''.join('%s%d' % (k,v) for k,v in sorted(result.iteritems(),key=lambda x:x[1]))
'd2g2f2w3q5'
Once you have the dict solution, just use join to join them into a string:
''.join([k+str(v) for k,v in result.iteritems()])
You can replace the '' with whatever separater (including none) you want between numbers
Another approach, avoiding the % interpolation (or format()) by using join() only:
''.join(''.join((k, str(v))) for k,v in mydict.items())

Categories