Bir dizenin sayı içerip içermediğini kontrol edin


196

Bulduğum soruların çoğu, sayılarında harf aradıkları konusunda önyargılıyken, sayısız dize olmasını istediğim şeylerde rakamlar arıyorum. Bir dize girmek ve herhangi bir sayı içeriyor ve reddetmek olmadığını kontrol etmek gerekir.

İşlev isdigit()yalnızca TrueTÜM karakterlerden sayılar varsa geri döner . Sadece kullanıcının bir sayı gibi bir cümle girip girmediğini görmek istiyorum "I own 1 dog".

Herhangi bir fikir?

Yanıtlar:


295

anyFonksiyonu şu str.isdigitfonksiyonla kullanabilirsiniz:

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

Alternatif olarak, bunun gibi bir Normal İfade kullanabilirsiniz

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

Negatif sayılar ne olacak?
Ray

@Ray Daha sonra RegEx böyle genişletilebilirr'-?\d+'
thefourtheye

15
Orijinal normal ifade yine de negatif sayıları algılamaz mı?
confused00

1
@ confused00 Hayır, \daralıkta yalnızca tek haneyi eşleşir 0için 9.
thefourtheye

9
@thefourtheye: -1 hala bir rakam. Bu bir tire ve onu takip eden '1'
rakamıdır

50

Sen bir arada kullanabilir anyve str.isdigit:

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

TrueDizede bir basamak varsa işlev geri döner False.

Demo:

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

Geçici bir liste oluşturmanıza gerek yok, sadece bu köşeli parantezleri kaldırarak bir jeneratör ifadesi kullanabilirsiniz.
Matteo Italia

Ah evet, bunun anyjeneratör ifadelerini kabul ettiğini fark ettim .
aIKid


28

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

Normal ifadeyi kullanmanız daha iyi olur. Çok daha hızlı.

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 hiçbir şey
döndürmüyor

Bu, eşleşme olmadığı anlamına gelir, geri dönerNone
zyxue

RE_D = yeniden derleme ('\ d') def has_digits (dize): res = RE_D.search (dize) dönüş res değil Yok
Raul

8

Dizedeki her karaktere isdigit () işlevini uygulayabilirsiniz. Veya düzenli ifadeler kullanabilirsiniz.

Ayrıca Python bir dize bir sayı nasıl bulurum bulundu ? sayıları döndürmek için çok uygun yollarla. Aşağıdaki çözüm bu sorunun cevabından kaynaklanmaktadır.

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

Alternatif:

number = filter(str.isdigit, yourString)

Daha fazla bilgi için regex belgesine bakınız: http://docs.python.org/2/library/re.html

Düzenleme: Bu, boole değerini değil gerçek sayıları döndürür, böylece yukarıdaki yanıtlar sizin durumunuz için daha doğru olur

İlk yöntem, ilk basamağı ve sonraki ardışık basamakları döndürür. Böylece 1.56, 1 olarak iade edilecektir. 10.000, 10 olarak döndürülecektir. 0207-100-1000, 0207 olarak iade edilecektir.

İkinci yöntem çalışmıyor.

Tüm basamakları, noktaları ve virgülleri ayıklamak ve ardışık olmayan basamakları kaybetmemek için şunu kullanın:

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

3

Bunun için NLTK yöntemini kullanabilirsiniz.

Bu, metinde hem '1'i hem de' Bir'i bulur:

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

Bir sayının aralığa göre kontrol ederek dizede kaç kez göründüğünü kontrol etmek için count ile aralığı kullanabilirsiniz:

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

Bence kimse bu kombinasyon Mentionned olduğunu şaşırdım anyve map:

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

Python 3'te muhtemelen en hızlı (belki de regexes hariç) herhangi bir döngü içermemesidir (ve fonksiyonun yumuşatılması içine bakmaktan kaçınır str).

Olarak piton 2'de olduğu kullanmayın mapgetiri bir list, sonları anykısa devre


2

Peki ya bu?

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
Lütfen kaynak kodunuzu buraya atmayın. İyi olun ve cevabınıza hoş bir açıklama yapmaya çalışın, böylece diğerleri hoşuna gidecek ve oylarını oylayacak. Bkz: İyi bir cevabı nasıl yazarım?
sɐunıɔ ןɐ qɐp

2

@Zyxue cevabını biraz daha açık hale getireceğim:

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

@zyxue'nin cevapta önerdiği çözümlerden en hızlı kıyaslama olan çözümdür.


1

Çözmenin daha basit yolu

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

1
Stack Overflow'a hoş geldiniz! Lütfen kaynak kodunuzu buraya atmayın. İyi olun ve cevabınıza hoş bir açıklama yapmaya çalışın, böylece diğerleri hoşuna gidecek ve oylarını oylayacak. Bkz: İyi bir cevabı nasıl yazarım?
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)

Bu kod, en azından büyük harf, küçük harf ve rakam içeren n boyutuna sahip bir dizi oluşturur. While döngüsünü kullanarak bu etkinliği garanti ettik.


Lütfen cevabınıza açıklama ekleyin
Mastisa

1

anyve ordaşağıda gösterildiği gibi amaca hizmet etmek için birleştirilebilir.

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

Bu uygulama hakkında birkaç nokta.

  1. any C dilinde kısa devre ifadesi gibi çalıştığı ve 'a1bbbbbbc' 'b ve' c dizeleri karşılaştırılamayacak şekilde belirlenebildiği anda sonuç döndüreceği için daha iyidir.

  2. ordyalnızca '0' ve '5' arasındaki kontrol sayıları veya başka bir aralık gibi daha fazla esneklik sağladığı için daha iyidir. Örneğin, Onaltılı sayıların temsili için bir doğrulayıcı yazarsanız, dizenin yalnızca 'A' ila 'F' aralığında alfabe içermesini istersiniz.


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)

Bu, alfabe ve sayı içeren tüm dizeyi döndürür. isalpha (), dizeyi tüm basamaklarla veya tüm karakterlerle döndürür.


0

Bu muhtemelen Python'daki en iyi yaklaşım değildir, ancak bir Haskeller olarak bu lambda / harita yaklaşımı benim için mükemmel bir anlam ifade etti ve çok kısa:

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

Elbette adlandırılması gerekmez. anydigit("abc123")Aradığım gibi kullanılabilir , aradığım şey gibi geliyor!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.