44

I am trying to make a function to detect how many digits, letter, spaces, and others for a string.

Here's what I have so far:

def count(x):
    length = len(x)
    digit = 0
    letters = 0
    space = 0
    other = 0
    for i in x:
        if x[i].isalpha():
            letters += 1
        elif x[i].isnumeric():
            digit += 1
        elif x[i].isspace():
            space += 1
        else:
            other += 1
    return number,word,space,other

But it's not working:

>>> count(asdfkasdflasdfl222)
Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    count(asdfkasdflasdfl222)
NameError: name 'asdfkasdflasdfl222' is not defined

What's wrong with my code and how can I improve it to a more simple and precise solution?

ivanleoncz
  • 9,070
  • 7
  • 57
  • 49
ray
  • 641
  • 2
  • 8
  • 13
  • 4
    What does your code do that it shouldn't? What _should_ it do? What has your investigation revealed about the reason for the discrepancy? – jscs Jul 22 '14 at 03:02
  • 1
    ... this question is both off-topic as typo (you missed a pair of quotes, see [this answer](https://stackoverflow.com/a/45122891)) (at least there is a MCVE...) | and [ask many question at once](https://meta.stackexchange.com/questions/122174) (1: what's wrong, 2: how to improve it). Question 2 is mostly opinion-based and more suitable for [codereview.se] (did codereview exist in '14?) | – user202729 Jun 25 '18 at 03:05
  • I think the only reason the question is upvoted is because [this answer](https://stackoverflow.com/a/24878232) (which doesn't even solve the error (question 1), and rewrite the code to no longer use a function) can be helpful to many people. ||| [This question was *linked to* on Meta](https://meta.stackoverflow.com/questions/370051/why-did-an-answer-that-i-wrote-get-downvoted). – user202729 Jun 25 '18 at 03:06

12 Answers12

132

Here's another option:

s = 'some string'

numbers = sum(c.isdigit() for c in s)
letters = sum(c.isalpha() for c in s)
spaces  = sum(c.isspace() for c in s)
others  = len(s) - numbers - letters - spaces
skanalytic
  • 13
  • 2
Óscar López
  • 232,561
  • 37
  • 312
  • 386
  • 1
    @sundarnatarajСундар it's a trade-off. Sure, it iterates 3 times over the input string, but I believe it's easier to read like this. – Óscar López Jul 22 '14 at 03:09
  • 19
    +1 The solution is cleaner when you separate the tasks. Nice work! To make it fast, consider using *itertools.imap()* like this: ``numbers = sum(imap(str.isdigit, s))``. After the initial calls, that will run at C-speed with no pure python steps and no method lookups. – Raymond Hettinger Jul 22 '14 at 03:15
  • @ShubhamS.Naik True is taken as 1 for the purpose of a sum – Óscar López Dec 26 '17 at 14:33
  • Thanks @ÓscarLópez I agree that True is taken as 1, however I want to know numbers = sum(c.isdigit() for c in s) is generating which iterable?? As sum(1) returns as below: >>> sum(1) Traceback (most recent call last): File "", line 1, in TypeError: 'int' object is not iterable – Shubham S. Naik Dec 26 '17 at 14:44
  • The inside of sum is a generator expression, I simply removed the surrounding () because they’re redundant – Óscar López Dec 26 '17 at 15:02
  • @ÓscarLópez which data structure (iterable) does it generate ? – Shubham S. Naik Dec 26 '17 at 15:46
  • As I said: a generator expression. Read about it in the docs. – Óscar López Dec 26 '17 at 15:50
  • @ÓscarLópez I will read about 'generator expression' . Thanks a lot !! – Shubham S. Naik Dec 26 '17 at 16:21
  • The solution given by @RaymondHettinger using `imap` is for Python 2. For Python 3, use the built in `map` function. For example, `sum(map(str.isdigit, s))`. – Imran Mar 02 '23 at 07:57
10

Following code replaces any nun-numeric character with '', allowing you to count number of such characters with function len.

import re
len(re.sub("[^0-9]", "", my_string))

Alphabetical:

import re
len(re.sub("[^a-zA-Z]", "", my_string))

More info - https://docs.python.org/3/library/re.html

brickbobed
  • 169
  • 1
  • 10
3

You shouldn't be setting x = []. That is setting an empty list to your inputted parameter. Furthermore, use python's for i in x syntax as follows:

for i in x:
    if i.isalpha():
        letters+=1
    elif i.isnumeric():
        digit+=1
    elif i.isspace():
        space+=1
    else:
        other+=1
sshashank124
  • 31,495
  • 9
  • 67
  • 76
  • the indentation is right( got wrong when copy to stackoverflow). the reason I used x=[] is try to let Python know that x is a list. if I delete x=[], it showed : >>> count(aasdfs1111xxx) Traceback (most recent call last): File "", line 1, in count(aasdfs1111xxx) NameError: name 'aasdfs1111xxx' is not defined – ray Jul 22 '14 at 22:14
2

To count the number of letters in a string:

def iinn():        # block for numeric strings
      
   b=(input("Enter numeric letter string "))

   if b.isdigit():
       print (f"you entered {b} numeric string" + "\n")
            
   else:
    
       letters = sum(c.isalpha() for c in b)
       print (f"in the string {b} are {letters} alphabetic letters")
       print("Try again...","\n")        
    
   while True:
       iinn()

A block of numeric strings will be in inverse order:

numbers = sum(c.isdigit() for c in b)
Vega
  • 27,856
  • 27
  • 95
  • 103
1

# Write a Python program that accepts a string and calculate the number of digits 
# andletters.

    stre =input("enter the string-->")
    countl = 0
    countn = 0
    counto = 0
    for i in stre:
        if i.isalpha():
            countl += 1
        elif i.isdigit():
            countn += 1
        else:
            counto += 1
    print("The number of letters are --", countl)
    print("The number of numbers are --", countn)
    print("The number of characters are --", counto)
mxschumacher
  • 37
  • 1
  • 7
1

If you want a simple solution, use list comprehension, then get len of that list:

len([ch for ch in text if ch.isdigit()])

This can be applied to isalpha() in a similar fashion

Mason Le
  • 11
  • 1
0

There are 2 errors is this code:

1) You should remove this line, as it will reqrite x to an empty list:

x = []

2) In the first "if" statement, you should indent the "letter += 1" statement, like:

if x[i].isalpha():
    letters += 1
Abhishek Mittal
  • 356
  • 1
  • 16
  • HI, If I removed x = [], the it got error when I run. it said the strings I typed is " not defined". – ray Jul 22 '14 at 22:18
  • I execute this code by comment out x = [] and it is working fine. One more error in your code is that you need to use isdigit instead of isnumberic. Here, I am assuming that count function is called by passing string in x argument. Like : count ("1233AASD 43") Please let me know if it does not solve your problem. – Abhishek Mittal Jul 23 '14 at 03:26
0

Ignoring anything else that may or may not be correct with your "revised code", the issue causing the error currently quoted in your question is caused by calling the "count" function with an undefined variable because your didn't quote the string.

  • count(thisisastring222) looks for a variable called thisisastring222 to pass to the function called count. For this to work you would have to have defined the variable earlier (e.g. with thisisastring222 = "AStringWith1NumberInIt.") then your function will do what you want with the contents of the value stored in the variable, not the name of the variable.
  • count("thisisastring222") hardcodes the string "thisisastring222" into the call, meaning that the count function will work with the exact string passed to it.

To fix your call to your function, just add quotes around asdfkasdflasdfl222 changing count(asdfkasdflasdfl222) to count("asdfkasdflasdfl222").

As far as the actual question "How to count digits, letters, spaces for a string in Python", at a glance the rest of the "revised code" looks OK except that the return line is not returning the same variables you've used in the rest of the code. To fix it without changing anything else in the code, change number and word to digit and letters, making return number,word,space,other into return digit,letters,space,other, or better yet return (digit, letters, space, other) to match current behavior while also using better coding style and being explicit as to what type of value is returned (in this case, a tuple).

3D1T0R
  • 1,050
  • 7
  • 17
0
sample = ("Python 3.2 is very easy") #sample string  
letters = 0  # initiating the count of letters to 0
numeric = 0  # initiating the count of numbers to 0

        for i in sample:  
            if i.isdigit():      
                numeric +=1      
            elif i.isalpha():    
                letters +=1    
            else:    
               pass  
letters  
numeric  
  • 2
    Welcome to StackOverflow. You better explain your solution, instead of just posting anonymous code. Maybe you should read [How do I write a good answer](https://stackoverflow.com/help/how-to-answer), especially when it says _Brevity is acceptable, but fuller explanations are better_. – Massimiliano Kraus Aug 07 '17 at 11:06
0
def match_string(words):
    nums = 0
    letter = 0
    other = 0
    for i in words :
        if i.isalpha():
            letter+=1
        elif i.isdigit():
            nums+=1
        else:
            other+=1
    return nums,letter,other

x = match_string("Hello World")
print(x)
>>>
(0, 10, 2)
>>>
0

This is a mistake in your calling. You are calling the code with the argument (asdfkasdflasdfl222) which is interpreted as a variable. However, you should call it with the string "asdfkasdflasdfl222".

-1

INPUT :

1

26

sadw96aeafae4awdw2 wd100awd

import re

a=int(input())
for i in range(a):
    b=int(input())
    c=input()

    w=re.findall(r'\d',c)
    x=re.findall(r'\d+',c)
    y=re.findall(r'\s+',c)
    z=re.findall(r'.',c)
    print(len(x))
    print(len(y))
    print(len(z)-len(y)-len(w))

OUTPUT :

4

1

19

The four digits are 96, 4, 2, 100 The number of spaces = 1 number of letters = 19

Arpitt Desai
  • 111
  • 1
  • 2
  • This doesn't actually answer the question. The question was to count the number of digits, letters and spaces, not to find all instances of numbers. – Tim Oct 04 '18 at 13:16