Sprawdź, czy ciąg zawiera liczbę


194

Większość pytań, które znalazłem, jest stronnicza w tym, że szukają liter w swoich liczbach, podczas gdy szukam liczb w ciągach, w których chciałbym być ciągiem niezliczonych liczb. Muszę wpisać ciąg i sprawdzić, czy zawiera on jakieś liczby i czy go odrzuca.

Funkcja isdigit()zwraca tylko Truewtedy, gdy WSZYSTKIE znaki są cyframi. Chcę tylko sprawdzić, czy użytkownik wprowadził numer, a więc zdanie takie jak "I own 1 dog"czy coś takiego.

Jakieś pomysły?

Odpowiedzi:


293

Możesz użyć anyfunkcji z str.isdigitfunkcją w ten sposób

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

Alternatywnie możesz użyć wyrażenia regularnego, takiego jak to

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

Co z liczbami ujemnymi?
Ray

@Ray Następnie RegEx można przedłużyć w ten sposóbr'-?\d+'
theourourheheye

15
Czy oryginalne wyrażenie regularne i tak nie wykrywa liczb ujemnych?
zmieszany 00

1
@ confused00 Nie, \ddopasuje tylko jedną cyfrę w zakresie 0do 9.
theourourhehe

9
@tourfhetye: -1 wciąż jest cyfrą. Jest to myślnik, po którym następuje cyfra „1”
użytkownik3183018

50

Możesz użyć kombinacji anyi str.isdigit:

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

Funkcja zwróci, Truejeśli w ciągu istnieje cyfra. W przeciwnym razieFalse . W .

Próbny:

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

Nie trzeba tworzyć tymczasowej listy, zamiast tego można użyć wyrażenia generatora, usuwając tylko nawiasy kwadratowe.
Matteo Italia,

Ach tak, właśnie zrozumiałem, że anyakceptuje wyrażenia generatora.
aIKid


28

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

Lepiej użyj wyrażenia regularnego. Jest znacznie szybszy.

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 nic nie zwraca
pyd

Oznacza to, że nie ma dopasowania, zwracaNone
zyxue

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

8

Możesz zastosować funkcję isdigit () do każdego znaku w ciągu. Lub możesz użyć wyrażeń regularnych.

Znalazłem również Jak znaleźć jedną liczbę w ciągu znaków w Pythonie? z bardzo odpowiednimi sposobami zwracania liczb. Poniższe rozwiązanie pochodzi z odpowiedzi na to pytanie.

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

Alternatywnie:

number = filter(str.isdigit, yourString)

Aby uzyskać więcej informacji, zobacz dokumentację regularną: http://docs.python.org/2/library/re.html

Edycja: Zwraca rzeczywiste liczby, a nie wartość logiczną, więc powyższe odpowiedzi są bardziej poprawne w twoim przypadku

Pierwsza metoda zwróci pierwszą cyfrę i kolejne kolejne cyfry. Zatem 1,56 zostanie zwrócone jako 1. 10 000 zostanie zwrócone jako 10. 0207-100-1000 zostanie zwrócone jako 0207.

Druga metoda nie działa.

Aby wyodrębnić wszystkie cyfry, kropki i przecinki i nie zgubić kolejnych cyfr, użyj:

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

3

Możesz do tego użyć metody NLTK.

W tekście znajdzie się zarówno „1”, jak i „jeden”:

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

Możesz to zrobić w następujący sposób:

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

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

Używanie .isdigit()oznacza także brak konieczności uciekania się do obsługi wyjątków (try / wyjątek) w przypadkach, w których musisz użyć rozumienia listy (próba / wyjątek nie jest możliwa w ramach rozumienia listy).


2

Możesz użyć zakresu z liczbą, aby sprawdzić, ile razy liczba pojawia się w ciągu, sprawdzając ją względem zakresu:

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

Dziwi mnie, że nikt nie wspomniał o tej kombinacji anyi map:

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

w Pythonie 3 prawdopodobnie jest tam najszybszy (z wyjątkiem być może wyrażeń regularnych), ponieważ nie zawiera żadnej pętli (a aliasing funkcji unika wyszukiwania str).

Nie używaj tego w Pythonie 2, ponieważ mapzwraca a list, które przerywa anyzwarcie


2

A co z tym?

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
Proszę nie rzucać tutaj tylko kodu źródłowego. Bądź miły i postaraj się podać ładny opis swojej odpowiedzi, aby inni polubili ją i głosowali za nią. Zobacz: Jak napisać dobrą odpowiedź?
sɐunıɔ ןɐ qɐp

2

Sprawię, że odpowiedź @zyxue będzie bardziej wyraźna:

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

które jest rozwiązaniem z najszybszym testem porównawczym spośród rozwiązań zaproponowanych przez @zyxue w odpowiedzi.


1

Prostszym sposobem rozwiązania jest jak

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

1
Witamy w Stack Overflow! Proszę nie rzucać tutaj tylko kodu źródłowego. Bądź miły i postaraj się podać ładny opis swojej odpowiedzi, aby inni polubili ją i głosowali za nią. Zobacz: Jak napisać dobrą odpowiedź?
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)

Ten kod generuje sekwencję o rozmiarze n, która przynajmniej zawiera wielkie litery, małe litery i cyfrę. Korzystając z pętli while, gwarantujemy to zdarzenie.


Dodaj wyjaśnienie do swojej odpowiedzi
Mastisa,

1

anyi ordmożna je łączyć, aby osiągnąć cel, jak pokazano poniżej.

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

Kilka uwag na temat tej implementacji.

  1. any jest lepszy, ponieważ działa jak wyrażenie zwarcia w języku C i zwróci wynik, gdy tylko będzie można go określić, tj. w przypadku łańcucha „a1bbbbbbc” b i „c” nawet nie zostaną porównane.

  2. ordjest lepszy, ponieważ zapewnia większą elastyczność, np. numery kontrolne tylko między „0” a „5” lub dowolnym innym zakresem. Na przykład, jeśli chcesz napisać walidator dla szesnastkowej reprezentacji liczb, chciałbyś, aby ciąg zawierał alfabety tylko w zakresie od „A” do „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)

Zwraca cały ciąg zawierający zarówno alfabety, jak i liczby. isalpha () zwraca ciąg zawierający wszystkie cyfry lub wszystkie znaki.


0

To prawdopodobnie nie jest najlepsze podejście w Pythonie, ale jako Haskeller to podejście lambda / mapa miało dla mnie idealny sens i jest bardzo krótkie:

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

Oczywiście nie trzeba go nazywać. Nazwany może być używany jak anydigit("abc123"), co wydaje mi się tym, czego szukałem!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.