Verifique se uma sequência contém um número

193

A maioria das perguntas que encontrei são tendenciosas pelo fato de estarem procurando letras em seus números, enquanto estou procurando por números no que eu gostaria de ser uma sequência sem número. Preciso digitar uma string e verificar se ela contém algum número e se a rejeita.

A função isdigit()retornará apenas Truese TODOS os caracteres forem números. Eu só quero ver se o usuário digitou um número para uma frase como "I own 1 dog"ou algo assim.

Alguma ideia?

DonnellyOverflow
fonte

Respostas:

291

Você pode usar a anyfunção, com a str.isdigitfunção, assim

>>> def hasNumbers(inputString):
...     return any(char.isdigit() for char in inputString)
... 
>>> hasNumbers("I own 1 dog")
True
>>> hasNumbers("I own no dog")
False

Como alternativa, você pode usar uma Expressão Regular, como esta

>>> import re
>>> def hasNumbers(inputString):
...     return bool(re.search(r'\d', inputString))
... 
>>> hasNumbers("I own 1 dog")
True
>>> hasNumbers("I own no dog")
False
thefourtheye
fonte
E os números negativos?
Raio
@Ray Então o RegEx pode ser estendido assimr'-?\d+'
thefourtheye
15
O regex original não detectaria os números negativos?
confused00
1
@ confused00 Não, \dcorresponderá apenas um único dígito no intervalo 0a 9.
thefourtheye 26/11/16
9
@thefourtheye: -1 ainda é um dígito. É um traço, seguido pelo dígito '1'
user3183018 27/02
49

Você pode usar uma combinação de anye str.isdigit:

def num_there(s):
    return any(i.isdigit() for i in s)

A função retornará Truese houver um dígito na string, caso contrário False.

Demo:

>>> king = 'I shall have 3 cakes'
>>> num_there(king)
True
>>> servant = 'I do not have any cakes'
>>> num_there(servant)
False
aIKid
fonte
Não há necessidade de criar uma lista temporária; você pode usar uma expressão de gerador apenas removendo os colchetes.
Matteo Italia
Ah sim, acabei de perceber que anyaceita expressões geradoras.
aIKid
30

usar

str.isalpha () 

Ref: https://docs.python.org/2/library/stdtypes.html#str.isalpha

Retorne true se todos os caracteres da string forem alfabéticos e houver pelo menos um caractere, caso contrário, false.

K246
fonte
8
Existem outros tipos de caracteres que não alfabéticos e numéricos - por exemplo, '_'.isalpha()é Falso.
Lvc #
28

https://docs.python.org/2/library/re.html

Você deve usar melhor a expressão regular. É muito mais rápido.

import re

def f1(string):
    return any(i.isdigit() for i in string)


def f2(string):
    return re.search('\d', string)


# if you compile the regex string first, it's even faster
RE_D = re.compile('\d')
def f3(string):
    return RE_D.search(string)

# Output from iPython
# In [18]: %timeit  f1('assdfgag123')
# 1000000 loops, best of 3: 1.18 µs per loop

# In [19]: %timeit  f2('assdfgag123')
# 1000000 loops, best of 3: 923 ns per loop

# In [20]: %timeit  f3('assdfgag123')
# 1000000 loops, best of 3: 384 ns per loop
zyxue
fonte
F3 não está retornando qualquer coisa
PYD
Isso significa que não há jogo, ele retornaNone
zyxue
RE_D = re.compile ('\ d') def has_digits (string): res = RE_D.search (string) retorno res não é nenhum
Raul
8

Você pode aplicar a função isdigit () em todos os caracteres da String. Ou você pode usar expressões regulares.

Também encontrei Como encontro um número em uma string no Python? com maneiras muito adequadas de retornar números. A solução abaixo é da resposta nessa pergunta.

number = re.search(r'\d+', yourString).group()

Alternativamente:

number = filter(str.isdigit, yourString)

Para mais informações, consulte o documento regex: http://docs.python.org/2/library/re.html

Editar: Retorna os números reais, não um valor booleano, portanto as respostas acima são mais corretas para o seu caso

O primeiro método retornará o primeiro dígito e os dígitos consecutivos subsequentes. Assim, 1,56 será retornado como 1, 10.000 será retornado como 10. 0207-100-1000 será retornado como 0207.

O segundo método não funciona.

Para extrair todos os dígitos, pontos e vírgulas e não perder dígitos não consecutivos, use:

re.sub('[^\d.,]' , '', yourString)
Haini
fonte
3

Você pode usar o método NLTK para isso.

Isso encontrará '1' e 'One' no texto:

import nltk 

def existence_of_numeric_data(text):
    text=nltk.word_tokenize(text)
    pos = nltk.pos_tag(text)
    count = 0
    for i in range(len(pos)):
        word , pos_tag = pos[i]
        if pos_tag == 'CD':
            return True
    return False

existence_of_numeric_data('We are going out. Just five you and me.')
Mahendra S. Chouhan
fonte
2

Você pode fazer isso da seguinte maneira:

if a_string.isdigit(): do_this() else: do_that()

https://docs.python.org/2/library/stdtypes.html#str.isdigit

Usar .isdigit()também significa não ter que recorrer ao tratamento de exceções (tentativa / exceção) nos casos em que você precisa usar a compreensão da lista (tentativa / exceção não é possível dentro de uma compreensão da lista).

olisteadman
fonte
2

Você pode usar o intervalo com contagem para verificar quantas vezes um número aparece na sequência, verificando-o no intervalo:

def count_digit(a):
    sum = 0
    for i in range(10):
        sum += a.count(str(i))
    return sum

ans = count_digit("apple3rh5")
print(ans)

#This print 2
pedmindset
fonte
2

Estou surpreso que ninguém tenha mencionado essa combinação de anye map:

def contains_digit(s):
    isdigit = str.isdigit
    return any(map(isdigit,s))

no python 3 é provavelmente o mais rápido (exceto talvez para expressões regulares) é porque ele não contém nenhum loop (e o apelido da função evita procurá-lo em str ).

Não use isso no python 2 como mapretorna a list, o que interrompe o anycurto-circuito

Jean-François Fabre
fonte
2

Que tal este?

import string

def containsNumber(line):
    res = False
    try:
        for val in line.split():
            if (float(val.strip(string.punctuation))):
                res = True
                break
    except ValueError:
        pass
    return res

containsNumber('234.12 a22') # returns True
containsNumber('234.12L a22') # returns False
containsNumber('234.12, a22') # returns True
aga
fonte
1
Por favor, não jogue apenas seu código fonte aqui. Seja gentil e tente dar uma boa descrição para sua resposta, para que outras pessoas gostem e votem. Veja: Como escrevo uma boa resposta?
sɐunıɔ ןɐ qɐp
2

Vou deixar a resposta @zyxue um pouco mais explícita:

RE_D = re.compile('\d')

def has_digits(string):
    res = RE_D.search(string)
    return res is not None

has_digits('asdf1')
Out: True

has_digits('asdf')
Out: False

que é a solução com a referência mais rápida das soluções que a @zyxue propôs na resposta.

Raul
fonte
1

A maneira mais simples de resolver é

s = '1dfss3sw235fsf7s'
count = 0
temp = list(s)
for item in temp:
    if(item.isdigit()):
        count = count + 1
    else:
        pass
print count
Nevasca
fonte
1
Bem-vindo ao Stack Overflow! Por favor, não jogue apenas seu código fonte aqui. Seja gentil e tente dar uma boa descrição para sua resposta, para que outras pessoas gostem e votem. Veja: Como escrevo uma boa resposta?
sɐunıɔ ןɐ qɐp
1
import string
import random
n = 10

p = ''

while (string.ascii_uppercase not in p) and (string.ascii_lowercase not in p) and (string.digits not in p):
    for _ in range(n):
        state = random.randint(0, 2)
        if state == 0:
            p = p + chr(random.randint(97, 122))
        elif state == 1:
            p = p + chr(random.randint(65, 90))
        else:
            p = p + str(random.randint(0, 9))
    break
print(p)

Esse código gera uma sequência com o tamanho n, que pelo menos contém maiúsculas, minúsculas e um dígito. Ao usar o loop while, garantimos este evento.

Mehran Attar
fonte
Por favor, adicione explicações à sua resposta
Mastisa
1

anye ordpode ser combinado para atender à finalidade, conforme mostrado abaixo.

>>> def hasDigits(s):
...     return any( 48 <= ord(char) <= 57 for char in s)
...
>>> hasDigits('as1')
True
>>> hasDigits('as')
False
>>> hasDigits('as9')
True
>>> hasDigits('as_')
False
>>> hasDigits('1as')
True
>>>

Alguns pontos sobre esta implementação.

  1. any é melhor porque funciona como expressão de curto-circuito na linguagem C e retornará o resultado assim que possível, ou seja, no caso da string 'a1bbbbbbc' 'b' e 'c' nem serão comparados.

  2. ordé melhor porque fornece mais flexibilidade, como números de verificação apenas entre '0' e '5' ou qualquer outro intervalo. Por exemplo, se você escrever um validador para representação hexadecimal de números, você deseja que a string tenha alfabetos no intervalo 'A' a 'F'.

ViFI
fonte
1
alp_num = [x for x in string.split() if x.isalnum() and re.search(r'\d',x) and 
re.search(r'[a-z]',x)]

print(alp_num)

Isso retorna toda a sequência que contém alfabetos e números. isalpha () retorna a string com todos os dígitos ou caracteres.

Sai ram
fonte
0

Esta provavelmente não é a melhor abordagem em Python, mas como Haskeller, essa abordagem lambda / map fazia sentido para mim e é muito curta:

anydigit = lambda x: any(map(str.isdigit, x))

Não precisa ser nomeado, é claro. Nomeado que poderia ser usado como anydigit("abc123"), que parece o que eu estava procurando!

Oscar South
fonte