Removing letters from a list of both numbers and letters

In the function I'm trying to write, the user enters a bunch of numbers, for example. "648392". I turn this line into a list like this: ['6', '4', '8', '3', '9', '2'].

I wanted to be able to sum with these numbers, so I turned the numbers from the list into integers, not strings. All this worked fine, however I also wanted the user to be able to enter letters, and then I just deleted them from the list - and that's where I got stuck. For example, the user enters "6483A2".

I can’t check if the element is a digit with isDigit because the elements must apparently be integers, and I cannot convert the elements in the list to integers because some of the elements are letters. I'm sure there is a simple solution, but I'm pretty terrible in python, so any help would be greatly appreciated!

+4
source share
7 answers

You can use str.translate to filter letters:

 >>> from string import letters >>> strs = "6483A2" >>> strs.translate(None, letters) '64832' 

There is no need to convert a string to a list, you can iterate through the string itself.

Using str.join , str.isdigit and a list of insights:

 >>> ''.join([c for c in strs if c.isdigit()]) '64832' 

or this is how you want sum digits:

 sum(int(c) for c in strs if c.isdigit()) 

Terms of comparison:

Tiny line:

 >>> strs = "6483A2" >>> %timeit sum(int(c) for c in strs.translate(None, letters)) 100000 loops, best of 3: 9.19 us per loop >>> %timeit sum(int(c) for c in strs if c.isdigit()) 100000 loops, best of 3: 10.1 us per loop 

Big line:

 >>> strs = "6483A2"*1000 >>> %timeit sum(int(c) for c in strs.translate(None, letters)) 100 loops, best of 3: 5.47 ms per loop >>> %timeit sum(int(c) for c in strs if c.isdigit()) 100 loops, best of 3: 8.54 ms per loop 

In the worst case, all letters:

 >>> strs = "A"*100 >>> %timeit sum(int(c) for c in strs.translate(None, letters)) 100000 loops, best of 3: 2.53 us per loop >>> %timeit sum(int(c) for c in strs if c.isdigit()) 10000 loops, best of 3: 24.8 us per loop >>> strs = "A"*1000 >>> %timeit sum(int(c) for c in strs.translate(None, letters)) 100000 loops, best of 3: 7.34 us per loop >>> %timeit sum(int(c) for c in strs if c.isdigit()) 1000 loops, best of 3: 210 us per loop 
+5
source

You can filter information from any iteration (including a string) using the filter function or understanding. For example, any of them:

 digits = filter(str.isdigit, input_string) digits = (character for character in input_string if character.isdigit()) 

... will give you an iterable figure. If you want to convert each of the numbers to numbers, then any of them will do this:

 numbers = map(int, filter(str.isdigit, input_string)) numbers = (int(character) for character in input_string if character.isdigit()) 

So, to get the sum of all the numbers, skipping the letters, just pass one of them to the sum function:

 total = sum(map(int, filter(str.isdigit, input_string))) total = sum(int(character) for character in input_string if character.isdigit()) 

From your last paragraph:

I cannot check if the element is a digit with isDigit, because the elements must apparently be integers, and I cannot convert the elements into a list to integers

At first it is isdigit , not isdigit . Secondly, isdigit is a method for strings, not integers, so you are mistaken in thinking that you cannot call it in strings. In fact, you have to call it in strings before converting them to integers.

But this brings up another option. In Python, it's often easier to ask forgiveness than permission . Instead of figuring out if we can convert each letter to int, and then do it, we can just try to convert it to int and then handle a possible glitch. For instance:

 def get_numbers(input_string): for character in input_string: try: yield int(character) except TypeError: pass 

Now just:

 total = sum(get_numbers(input_string)) 
+3
source

You can do this with the understanding:

 >>> s = "6483A2" >>> [int(c) for c in s if c.isdigit()] [6, 4, 8, 3, 2] >>> sum(int(c) for c in s if c.isdigit()) 23 

This approach is good if you want to go directly from the mixed string to a list of only integers, which is apparently your goal.

+2
source

You can use the expression and put it in sum .

 >>> import string >>> s '6483A2' >>> sum(int(x) for x in list(s) if x in string.digits) 23 

If no other module wants to import, use isdigit :

 sum(int(x) for x in list(s) if x.isdigit()) 
+1
source
 >>> a = "hello123987io" >>> b = "khj7djksh787" >>> sum([int(letter) for letter in b if letter.isdigit()]) 29 >>> sum([int(letter) for letter in a if letter.isdigit()]) 30 

 >>> def getInputAndSum(userInput): ... """ returns a tuple with the input string and its sum """ ... return userInput, sum([int(letter) for letter in userInput if letter.isdigit()]) ... >>> getInputAndSum("Th1s1550mesum") ('Th1s1550mesum', 12) 
+1
source

Just to make a small contribution if you want the aggregated amount to be able to do all of this:

 x = "6483A2" sum(map(int, filter(str.isdigit, x))) >>>23 

If you need a list of integers just for other purposes or another type of sum , then just leave it in map :

 map(int, filter(str.isdigit, x)) >>>[6, 4, 8, 3, 2] 

Note: About the string.letters approach. letters is locale dependent, so this is:

 import locale, string locale.setlocale(locale.LC_ALL, 'es_ES') # or 'esp_esp' if you're on Windows string.letters >>> "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzŠŚŽšśžźŞµşŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőöřůúűüýţ˙" 

Although I would recommend regex for this case, as suggested above :)

Nice to work together: D

+1
source

Although this is certainly true, you can filter the letters in different ways, perhaps more than Pythonic allows the interpreter to decide what can be interpreted as a number and what is not. Therefore, even if it is not one liner, you may prefer this approach:

 aninput = "648392A0&sle4" def discard_non_ints(itbl, rdx=10): for d in itbl: try: yield(int(d, rdx)) except ValueError: pass sum(discard_non_ints(aninput)) 36 

What is especially nice about this approach is that it gives you the flexibility to include decimal places. Want to summarize all the hexadecimal digits?

 sum(discard_non_ints('deadbeforenoon', 16)) 104 
0
source

Source: https://habr.com/ru/post/1495861/


All Articles