Überprüfen Sie, ob eine Zeichenfolge eine Zahl enthält


193

Die meisten Fragen, die ich gefunden habe, sind voreingenommen in Bezug auf die Tatsache, dass sie nach Buchstaben in ihren Zahlen suchen, während ich nach Zahlen in einer Zahl suche, die ich als zahllose Zeichenfolge bezeichnen möchte. Ich muss eine Zeichenfolge eingeben und prüfen, ob sie Zahlen enthält und ob sie diese ablehnt.

Die Funktion wird isdigit()nur zurückgegeben, Truewenn ALLE Zeichen Zahlen sind. Ich möchte nur sehen, ob der Benutzer eine Nummer eingegeben hat, also einen Satz wie "I own 1 dog"oder so.

Irgendwelche Ideen?

Antworten:


291

Sie können die anyFunktion mit dieser str.isdigitFunktion wie folgt verwenden

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

Alternativ können Sie einen regulären Ausdruck wie diesen verwenden

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

Was ist mit negativen Zahlen?
Ray

@ Ray Dann kann der RegEx so verlängert werdenr'-?\d+'
thefourtheye

15
Würde der ursprüngliche Regex die negativen Zahlen nicht trotzdem erkennen?
verwirrt00

1
@ confused00 Nein, stimmt \dnur mit einer einzelnen Ziffer im Bereich 0von überein 9.
thefourtheye

9
@thefourtheye: -1 ist immer noch eine Ziffer. Es ist ein Bindestrich, gefolgt von der Ziffer '1'
user3183018

49

Sie können eine Kombination aus anyund verwenden str.isdigit:

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

TrueAndernfalls wird die Funktion zurückgegeben, wenn eine Ziffer in der Zeichenfolge vorhanden ist False.

Demo:

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

Sie müssen keine temporäre Liste erstellen, sondern können stattdessen einen Generatorausdruck verwenden, indem Sie diese eckigen Klammern entfernen.
Matteo Italia

Ah ja, habe gerade festgestellt, dass dies anyGeneratorausdrücke akzeptiert.
aIKid


28

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

Sie sollten besser reguläre Ausdrücke verwenden. Es ist viel schneller.

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 gibt nichts zurück
pyd

Das heißt, es gibt keine Übereinstimmung, es kehrt zurückNone
Zyxue

RE_D = re.compile ('\ d') def has_digits (string): res = RE_D.search (string) return res ist nicht None
Raul

8

Sie können die Funktion isdigit () auf jedes Zeichen in der Zeichenfolge anwenden. Oder Sie könnten reguläre Ausdrücke verwenden.

Außerdem habe ich gefunden Wie finde ich eine Zahl in einer Zeichenfolge in Python? mit sehr geeigneten Möglichkeiten, Zahlen zurückzugeben. Die folgende Lösung ergibt sich aus der Antwort in dieser Frage.

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

Alternative:

number = filter(str.isdigit, yourString)

Weitere Informationen finden Sie im Regex-Dokument: http://docs.python.org/2/library/re.html

Bearbeiten: Dies gibt die tatsächlichen Zahlen zurück, keinen booleschen Wert, sodass die obigen Antworten für Ihren Fall korrekter sind

Die erste Methode gibt die erste Ziffer und nachfolgende aufeinanderfolgende Ziffern zurück. Somit wird 1,56 als 1 zurückgegeben. 10.000 werden als 10 zurückgegeben. 0207-100-1000 wird als 0207 zurückgegeben.

Die zweite Methode funktioniert nicht.

Verwenden Sie: Um alle Ziffern, Punkte und Kommas zu extrahieren und nicht aufeinanderfolgende Ziffern nicht zu verlieren:

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

3

Sie können dafür die NLTK-Methode verwenden.

Dies findet sowohl '1' als auch 'Eins' im Text:

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

Sie können dies wie folgt erreichen:

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

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

Verwenden .isdigit()bedeutet auch, dass Sie nicht auf die Ausnahmebehandlung zurückgreifen müssen (versuchen / ausnehmen ), wenn Sie das Listenverständnis verwenden müssen (versuchen / ausnehmen ist innerhalb eines Listenverständnisses nicht möglich).


2

Sie können den Bereich mit Anzahl verwenden, um zu überprüfen, wie oft eine Zahl in der Zeichenfolge angezeigt wird, indem Sie sie mit dem Bereich vergleichen:

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

Ich bin überrascht, dass niemand diese Kombination von anyund erwähnt hat map:

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

In Python 3 ist es wahrscheinlich das schnellste (außer vielleicht für reguläre Ausdrücke), da es keine Schleife enthält (und durch Aliasing der Funktion wird vermieden, dass nachgeschlagen wird str).

Verwenden Sie das in Python 2 nicht als mapRückgabe a list, wodurch der anyKurzschluss unterbrochen wird


2

Was ist mit diesem?

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
Bitte werfen Sie nicht nur Ihren Quellcode hierher. Sei nett und versuche, deiner Antwort eine nette Beschreibung zu geben, damit andere sie mögen und sie positiv bewerten. Siehe: Wie schreibe ich eine gute Antwort?
sɐunıɔ ןɐ qɐp

2

Ich werde die Antwort von @zyxue etwas expliziter machen:

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

Dies ist die Lösung mit dem schnellsten Benchmark aus den Lösungen, die @zyxue für die Antwort vorgeschlagen hat.


1

Einfacher zu lösen ist wie

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

1
Willkommen bei Stack Overflow! Bitte werfen Sie nicht nur Ihren Quellcode hierher. Sei nett und versuche, deiner Antwort eine nette Beschreibung zu geben, damit andere sie mögen und sie positiv bewerten. Siehe: Wie schreibe ich eine gute Antwort?
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)

Dieser Code generiert eine Sequenz mit der Größe n, die mindestens Groß-, Klein- und Ziffern enthält. Durch die Verwendung der while-Schleife haben wir dieses Ereignis garantiert.


Bitte fügen Sie Erklärung zu Ihrer Antwort hinzu
Mastisa

1

anyund ordkann kombiniert werden, um den unten gezeigten Zweck zu erfüllen.

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

Ein paar Punkte zu dieser Implementierung.

  1. any ist besser, weil es wie ein Kurzschlussausdruck in der C-Sprache funktioniert und das Ergebnis zurückgibt, sobald es bestimmt werden kann, dh im Fall der Zeichenfolge 'a1bbbbbbc' werden 'b' und 'c' nicht einmal verglichen.

  2. ordist besser, weil es mehr Flexibilität bietet, wie Prüfnummern nur zwischen '0' und '5' oder einem anderen Bereich. Wenn Sie beispielsweise einen Validator für die hexadezimale Darstellung von Zahlen schreiben, möchten Sie, dass die Zeichenfolge nur Alphabete im Bereich von 'A' bis 'F' enthält.


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)

Dies gibt alle Zeichenfolgen zurück, die sowohl Alphabete als auch Zahlen enthalten. isalpha () gibt die Zeichenfolge mit allen Ziffern oder allen Zeichen zurück.


0

Dies ist wahrscheinlich nicht der beste Ansatz in Python, aber als Haskeller machte dieser Lambda / Map-Ansatz für mich vollkommen Sinn und ist sehr kurz:

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

Muss natürlich nicht benannt werden. Benannt, es könnte so verwendet werden anydigit("abc123"), was sich so anfühlt, wie ich es gesucht habe!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.