Controlla se una stringa contiene un numero


196

La maggior parte delle domande che ho trovato sono distorte dal fatto che stanno cercando lettere nei loro numeri, mentre sto cercando numeri in quella che vorrei essere una stringa senza numero. Devo inserire una stringa e verificare se contiene numeri e se lo rifiuta.

La funzione isdigit()ritorna solo Truese TUTTI i caratteri sono numeri. Voglio solo vedere se l'utente ha inserito un numero così una frase simile "I own 1 dog"o qualcosa del genere.

Qualche idea?

Risposte:


295

È possibile utilizzare la anyfunzione, con la str.isdigitfunzione, in questo modo

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

In alternativa puoi usare un'espressione regolare, come questa

>>> import re
>>> def hasNumbers(inputString):
...     return bool(re.search(r'\d', inputString))
... 
>>> hasNumbers("I own 1 dog")
True
>>> hasNumbers("I own no dog")
False

E i numeri negativi?
Ray,

@Ray Quindi il RegEx può essere esteso in questo modor'-?\d+'
thefourtheye il

15
Il regex originale non rileverebbe comunque i numeri negativi?
confused00

1
@ confused00 No, \dcorrisponderà a una sola cifra nell'intervallo 0a 9.
thefourtheye il

9
@thefourtheye: -1 è ancora una cifra. È un trattino, seguito dalla cifra '1'
user3183018

50

Puoi usare una combinazione di any e str.isdigit:

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

La funzione tornerà Truese esiste una cifra nella stringa, altrimenti False.

demo:

>>> king = 'I shall have 3 cakes'
>>> num_there(king)
True
>>> servant = 'I do not have any cakes'
>>> num_there(servant)
False

Non è necessario creare un elenco temporaneo, è possibile utilizzare un'espressione del generatore invece semplicemente rimuovendo quelle parentesi quadre.
Matteo Italia,

Ah sì, ho appena capito che anyaccetta le espressioni del generatore.
aikid,


28

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

Dovresti usare meglio l'espressione regolare. È molto più veloce

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

f3 non restituisce nulla
pyd

Ciò significa che non c'è corrispondenza, ritornaNone
zyxue

RE_D = re.compile ('\ d') def has_digits (stringa): res = RE_D.search (stringa) restituisce res non è Nessuno
Raul

8

È possibile applicare la funzione isdigit () su tutti i caratteri nella stringa. Oppure potresti usare espressioni regolari.

Inoltre ho trovato Come trovo un numero in una stringa in Python? con modi molto adatti per restituire numeri. La soluzione che segue è dalla risposta a quella domanda.

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

In alternativa:

number = filter(str.isdigit, yourString)

Per ulteriori informazioni, consultare il documento regex: http://docs.python.org/2/library/re.html

Modifica: restituisce i numeri effettivi, non un valore booleano, quindi le risposte sopra riportate sono più corrette per il tuo caso

Il primo metodo restituirà la prima cifra e le successive cifre consecutive. Pertanto, 1,56 verrà restituito come 1. 10.000 verrà restituito come 10. 0207-100-1000 verrà restituito come 0207.

Il secondo metodo non funziona.

Per estrarre tutte le cifre, i punti e le virgole e non perdere le cifre non consecutive, utilizzare:

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

3

È possibile utilizzare il metodo NLTK per questo.

Questo troverà '1' e 'One' nel testo:

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.')

2

Puoi farlo come segue:

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

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

Usare .isdigit()significa anche non dover ricorrere alla gestione delle eccezioni (provare / tranne) nei casi in cui è necessario utilizzare la comprensione dell'elenco (provare / salvo non è possibile all'interno di una comprensione dell'elenco).


2

È possibile utilizzare l'intervallo con conteggio per verificare quante volte un numero appare nella stringa verificandolo rispetto all'intervallo:

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

2

Sono sorpreso che nessuno abbia menzionato questa combinazione di anye map:

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

in Python 3 è probabilmente il più veloce lì (tranne forse per le regex) perché non contiene alcun loop (e l'aliasing della funzione evita di cercarlo str).

Non usarlo in Python 2 come maprestituisce a list, che interrompe il anycorto circuito


2

Che dire di questo?

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

1
Per favore non gettare qui il tuo codice sorgente. Sii gentile e prova a dare una bella descrizione alla tua risposta, così che piacerà ad altri e la voterà. Vedi: Come posso scrivere una buona risposta?
sɐunıɔ ןɐ qɐp

2

Renderò la risposta @zyxue un po 'più esplicita:

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

che è la soluzione con il benchmark più veloce tra le soluzioni proposte da @zyxue sulla risposta.


1

Il modo più semplice per risolvere è come

s = '1dfss3sw235fsf7s'
count = 0
temp = list(s)
for item in temp:
    if(item.isdigit()):
        count = count + 1
    else:
        pass
print count

1
Benvenuto in Stack Overflow! Per favore non gettare qui il tuo codice sorgente. Sii gentile e prova a dare una bella descrizione alla tua risposta, così che piacerà ad altri e la voterà. Vedi: Come posso scrivere una buona risposta?
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)

Questo codice genera una sequenza con dimensione n che contiene almeno lettere maiuscole, minuscole e cifre. Usando il ciclo while, abbiamo garantito questo evento.


Per favore, aggiungi una spiegazione alla tua risposta
Mastisa,

1

anye ordpuò essere combinato per servire allo scopo come mostrato di seguito.

>>> 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
>>>

Un paio di punti su questa implementazione.

  1. any è meglio perché funziona come un'espressione di cortocircuito in linguaggio C e restituirà il risultato non appena può essere determinato, ad esempio nel caso della stringa 'a1bbbbbbc' 'b' e 'c non verranno nemmeno confrontati.

  2. ordè migliore perché offre una maggiore flessibilità come i numeri di controllo solo tra '0' e '5' o qualsiasi altro intervallo. Ad esempio, se si dovesse scrivere un validatore per la rappresentazione esadecimale dei numeri, si vorrebbe che la stringa avesse alfabeti nell'intervallo da 'A' a 'F'.


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)

Ciò restituisce tutta la stringa che contiene sia alfabeti che numeri. isalpha () restituisce la stringa con tutte le cifre o tutti i caratteri.


0

Questo probabilmente non è l'approccio migliore in Python, ma come Haskeller questo approccio lambda / mappa aveva perfettamente senso per me ed è molto breve:

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

Non ha bisogno di essere nominato ovviamente. Chiamato come potrebbe essere usato come anydigit("abc123"), che sembra quello che stavo cercando!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.