# Counting vowel, special characters, etc

sentence = input("What is your sentence?")
sentence=sentence.capitalize()
counta = sentence.count("a")
counte = sentence.count("e")
counti = sentence.count("i")
counto= sentence.count ("o")
countu= sentence.count ("u")
countA2 = sentence.count("A")
countE2 = sentence.count("E")
countI2 = sentence.count("I")
countO2 = sentence.count("O")
countU2 = sentence.count("U")
countI3 = sentence.count(" I ")
countspaces = sentence.count(" ")
a1 = sentence.count("!")
a2 = sentence.count(".")
a3 = sentence.count(">")
a4 = sentence.count("<")
a5 = sentence.count(":")
a6= sentence.count(";")
a7 = sentence.count("'")
a8 = sentence.count("@")
a9 = sentence.count("#")
a10 = sentence.count("~")
a11= sentence.count("{")
a12= sentence.count("}")
a13= sentence.count("[")
a14 = sentence.count("]")
a15 = sentence.count("-")
a16 = sentence.count("_")
a17 = sentence.count("+")
a18 = sentence.count("=")
a19 = sentence.count("£")
a20 = sentence.count("$") a21= sentence.count("%") a22 = sentence.count("^") a23= sentence.count("&") a24 = sentence.count("(") a25= sentence.count(")") a26=sentence.count("?") count = (counta + counte + counti + counto + countu + countA2 + countE2 + countI2 + countO2 + countU2 + countI3) speci= a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11+a12+a13+a14+a15+a16+a17+a18+a19+a20+a21+a22+a23+a24+a25+a26) print(sentence) print("This has", speci, "special characters") print("This has", countspaces, "Spaces") print("This has", count, "vowels")  • As we all want to make our code more efficient or improve it in one way or another, try to write a title that summarizes what your code does, not what you want to get out of a review. Please see How to get the best value out of Code Review - Asking Questions for guidance on writing good question titles. – BCdotWEB Jul 5 '16 at 10:49 • Holy crap. What exactly are you trying to do here and what made you think this is the most straight-forward way of implementing it? Welcome to Code Review! – Mast Jul 5 '16 at 11:04 • Welcome to Code Review! This question is incomplete. To help reviewers give you better answers, please add sufficient context to your question. The more you tell us about what your code does and what the purpose of doing that is, the easier it will be for reviewers to help you. Questions should include a description of what the code does – Mathias Ettinger Jul 5 '16 at 11:32 • I'd recommend investigating the string module, which has convenient ways to get your initial string of letters/digits/punctuation/whitespace. – Jeremy Weirich Jul 5 '16 at 13:28 ## 2 Answers You can use the built-in len function, list comprehensions and the in operator to greatly shorten this. You have much un-needed repetition and you don't need singular values as you just display their sum. Here is an example: VOWELS = "aeiou" vowels_count = len([char for char in sentence if char in VOWELS])  ## Code review Your formatting is inconsistent: a5 = sentence.count(":") a6= sentence.count(";") a7 = sentence.count("'") a8 = sentence.count("@") a9 = sentence.count("#") a10 = sentence.count("~") a11= sentence.count("{") a12= sentence.count("}")  I don't know why you chose that particular set of punctuation characters. For example, the " (double-quote) character is missing from that set. I have no idea why you are double-counting Is that appear as " I ". If you have a reason, you should write it in a comment. countI2 = sentence.count("I") … countI3 = sentence.count(" I ")  ## Discussion Oh, my. It's quite unclear exactly what task you are solving, but coming up with a proper specification of the task probably involves technical knowledge that you don't have, so I'm going to have to answer it multiple ways. I'll assume that you are using , though. Try running the following code: import re import unicodedata sentence = '“The quick brown dog jumpd [sic] over the lazy fox in İstanbul!"\u2003—\u2009allegedly.' space_count = sentence.count(' ') space_property_count = sum('Zs' == unicodedata.category(c) for c in sentence) special_count = sum(bool(re.match(r"""[!.><:;'@#~{}-_+=£$%^&()?]""", c)) for c in sentence)
punct_property_count = sum('P' in unicodedata.category(c) for c in sentence)
aeiouAEIOU_count = len(re.findall('[AEIOUaeiou]', sentence))
aeiou_ignorecase_count = len(re.findall('[aeiou]', sentence, re.IGNORECASE))

print(sentence)
print([unicodedata.category(c) for c in sentence])
print('This has {} SPACE characters'.format(space_count))
print('This has {} spaces (according to Unicode properties)'.format(space_property_count))
print('This has {} of the specific special characters'.format(special_count))
print('This has {} punctuation characters (according to Unicode properties)'.format(punct_property_count))
print('This has {} matches of "AEIOUaeiou"'.format(aeiouAEIOU_count))
print('This has {} case-insensitive matches of "aeiou"'.format(aeiou_ignorecase_count))


The output is:

“The quick brown dog jumpd [sic] over the lazy fox in İstanbul!" — allegedly.
['Pi', 'Lu', 'Ll', 'Ll', 'Zs', 'Ll', 'Ll', 'Ll', 'Ll', 'Ll', 'Zs', 'Ll', 'Ll', 'Ll', 'Ll', 'Ll', 'Zs', 'Ll', 'Ll', 'Ll', 'Zs', 'Ll', 'Ll', 'Ll', 'Ll', 'Ll', 'Zs', 'Ps', 'Ll', 'Ll', 'Ll', 'Pe', 'Zs', 'Ll', 'Ll', 'Ll', 'Ll', 'Zs', 'Ll', 'Ll', 'Ll', 'Zs', 'Ll', 'Ll', 'Ll', 'Ll', 'Zs', 'Ll', 'Ll', 'Ll', 'Zs', 'Ll', 'Ll', 'Zs', 'Lu', 'Ll', 'Ll', 'Ll', 'Ll', 'Ll', 'Ll', 'Ll', 'Po', 'Po', 'Zs', 'Pd', 'Zs', 'Ll', 'Ll', 'Ll', 'Ll', 'Ll', 'Ll', 'Ll', 'Ll', 'Ll', 'Po']
This has 11 SPACE characters
This has 13 spaces (according to Unicode properties)
This has 4 of the specific special characters
This has 7 punctuation characters (according to Unicode properties)
This has 18 matches of "AEIOUaeiou"
This has 19 case-insensitive matches of "aeiou"

As you can see, I've used six different counting techniques! Which one is the best? It depends!

• sentence.count(' ')

That is a straightforward count, which you have already used yourself. There are 11 SPACE characters between the double quotes.

• sum('Zs' == unicodedata.category(c) for c in sentence)

But what is a space? Actually, there are several kinds of space characters in Unicode other than the usual U+0020 SPACE character. To count all of them, you should use unicodedata.category() and count the characters that are categorized as 'Zs'. For a list of the possible categories, you have to consult the Unicode standard.

In the example above, in addition to the 11 spaces previously mentioned, there is also a U+2003 EM SPACE and a U+2009 THIN SPACE before and after the dash.

The built-in sum() function is a handy way to count a bunch of true/false values. As you might expect, sum([1, 0, 5]) equals 6. However, sum([True, False, 5]) also produces 6 — the True is treated as 1 and the False is treated as 0.

('Zs' == unicodedata.category(c) for c in sentence) is a generator expression.

• sum(bool(re.match(r"""[!.><:;'@#~{}-_+=£$%^&()?]""", c)) for c in sentence) Here, I'm using the sum(generator expression) technique again, except that this time I'm asking whether each character c in the sentence matches a pattern that I'm looking for. Specifically, the pattern is [!.><:;'@#~{}-_+=£$%^&()?]


As the regular expression tutorial states, the outer [ and ] characters mean "match any of the inner characters" — the ones that you listed in a1 through a26. Note that the inner [ and ] characters need to be quoted with a backslash so that they don't prematurely close the character class.

The re.match(…) call produces either an object (if the match is successful) or None (if c does not fit the pattern). bool(…) converts that to either True or False, respectively. As before, sum() counts the True values.

This finds 4 punctuation characters: [, ], !, and ..

• sum('P' in unicodedata.category(c) for c in sentence)

This is similar to looking for 'Zs', except that here, we are looking for 'Pc' (Connector Punctuation), 'Pd' (Dash Punctuation), 'Ps' (Open Punctuation), 'Pe' (Close Punctuation), 'Pi' (Initial Punctuation), 'Pf' (Final Punctuation), or 'Po' (Other Punctuation).

In addition to the four punctuation characters previously found, this also matches “ (U+201C LEFT DOUBLE QUOTATION MARK), " (U+0022 QUOTATION MARK), and — (U+2014 EM DASH).

• len(re.findall('[AEIOUaeiou]', sentence))

This is a less cumbersome alternative to the sum() technique I used above with sum(bool(re.match(…) …)). re.findall() returns a list of all the occurrences of the letters of interest, and len() gives the length of that list.

Note that I've refrained from calling the result "vowels", since what counts as a vowel is ambiguous. For example, 'y' is sometimes a vowel in English. 'w' is a semivowel in English, and a proper vowel in Welsh.

• len(re.findall('[aeiou]', sentence, re.IGNORECASE))

Unicode is full of tricky technicalities. For example, a U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE, which often appears in Turkish text, is considered an uppercase variant of U+0069 LATIN SMALL LETTER I — the i that we are familiar with.

In summary, you should use some of the techniques suggested above, depending on exactly what characters you intend to count.

• Wow, congrats for finding so many different methods, but I would state more clearly that in a normal program one of this methods should be used, avoiding counting each class of chars with a different method. – Caridorc Jul 7 '16 at 14:07
• @Caridorc The appropriate methods to use really do depend on the goal, though. I wouldn't mix-and-match sum(bool(re.match(…)) with len(re.findall(…)), but it is entirely reasonable to need both unicodedata and regex-based approaches, if that's what the task requires. – 200_success Jul 7 '16 at 16:55
• Yes, I agree, expressing unicode is better with their classes than regex. – Caridorc Jul 7 '16 at 16:58
• @Caridorc Unfortunately, Python regexes do not appear to support character property tests, as in Perl and Java. – 200_success Jul 7 '16 at 17:02
• Yes, but unicodedata looks just as good so I do not think this is a problem. – Caridorc Jul 7 '16 at 17:14