Dize Python'da Bir Sayı İçerirse Kontrol Edin

Giriş

İster kullanıcı girişi için bir doğrulama komut dosyası, ister kullanıcılardan parolaya bir karakter eklemelerini isteyen bir oturum açma formu oluşturuyor olun; bir dizenin karakter içerip içermediğini kontrol etmek alışılmadık bir işlem değildir.

Bu öğreticide – sonunda en verimli yaklaşım için bir kıyaslama da dahil olmak üzere Python'da bir dizenin bir rakam/sayı içerip içermediğini kontrol edebileceğiniz birçok yola göz atacağız.

Dize Python'da Sayı İçeriyorsa Kontrol Edin

olup olmadığını kontrol etmenin birçok yolu vardır. karakter bir sayıdır (ord(), isnumeric(), isdigit()), en azından tek bir pozitif isabet olup olmadığını kontrol etmek için bir for-loop ile birleştirebilirsiniz. Alternatif olarak, esnek, güçlü ve geniş metin kümelerine uygulanmak üzere tasarlanmış genel kalıp eşleyiciler olarak Normal İfadeleri kullanabilirsiniz. Son olarak - her zaman yapabilirsiniz map() koşullu bir ifade verilen her karakter ve dönüş True is any() bunların sonucu True.

Bunlar arasında seçim yaparken, yöntemlerin verimliliği, ayrıntı düzeyi ve kodlama stilinin yanı sıra işlemle ilgili yukarı veya aşağı akış görevleri dikkate alınmalıdır.

Dizenin sayı içerip içermediğini ord() ile kontrol edin

The ord() işlev bir karakter alır ve değerini döndürür ASCII değeri:

print(ord('0')) 
print(ord('9')) 

ASCII değeri 0 48 ve ASCII değeri 9 57'dir. Bunlar arasındaki herhangi bir sayı, uzantısı gereği, 48 ile 57 arasında bir ASCII değerine sahip olmak. Şimdi dizgede herhangi bir sayı olup olmadığını kontrol etmek için, tüm giriş dizisini dolaşacağız ve her karakterin ASCII değerini kontrol edeceğiz, ASCII değeri 47'den büyük ve 58'den küçükse, bu sayı demektir ve geri döneceğiz True:

input_string = "My name is Satyam & I am 22 yrs old"
flag = False
for ch in input_string:
    ascii_code = ord(ch)
    if 47 < ascii_code < 58:
        flag = True
        break
if flag:
    print("Yes, the string contains a number.")
else:
    print("No, the string does not contain a number.")

Bunun sonucu:

Yes, the string contains a number.

Dizenin sayı içerip içermediğini isnumeric() ile kontrol edin

The isnumeric() fonksiyon döner True giriş dizesi yalnızca sayılar içeriyorsa, aksi halde döndürür False:

str1 = "918"
print("String is whole numeric?", str1.isnumeric())
str2 = "The meaning of the universe is 42"
print("String is whole numeric?", str2.isnumeric())

Bunun sonucu:

String is whole numeric? True 
String is whole numeric? False

Not: The isnumeric() işlev beklediğiniz gibi davranmayacak negatif veya kayan sayılar. Yalnızca negatif veya kayan sayılardan oluşan bir dize iletirsek, geri döner FalseÇünkü - ve . Negatif sayılarla ve değişkenlerle ilişkilendirilen karakterler aslında sayı değildir.

str1 = "-918"
print("String is whole numeric?", str1.isnumeric()) 

str2 = "91.8"
print("String is whole numeric?", str2.isnumeric()) 

Yine de, Python'da karakterler yalnızca 1 uzunluğundaki dizeler olduğundan, karakterleri yineleyebilir ve kullanabilirsiniz. isnumeric() sayı olup olmadığını kontrol etmek için:

input_string = "My name is Satyam & I am 22 yrs old"
flag = False
for ch in input_string:
    if ch.isnumeric():
        flag = True
        break
if flag:
    print("Yes, the string contains a number.")
else:
    print("No, the string does not contain a number.")

Dizenin sayı içerip içermediğini isdigit() ile kontrol edin

The isdigit() işlev, bir dizideki tüm karakterlerin rakam olup olmadığını kontrol eder. Evet ise - geri döner Trueve değilse, döndürür False. Yine, Python'da karakterler yalnızca 1 uzunluğundaki dizeler olduğundan, bu yöntem her karakter için bir döngüde kullanılabilir:

input_string = "My name is Satyam & I am 22 yrs old"
flag = False
for ch in input_string:
    if ch.isdigit():
        flag = True
        break
if flag:
    print("Yes, the string contains a number.")
else:
    print("No, the string does not contain a number.")

Not: The isdigit() yöntem yalnızca aynı şekilde davranır isnumeric()ve ona kayan nokta veya negatif bir sayı içeren bir dize iletirseniz, False özel karakterlerin sayı olmaması nedeniyle döndürülür. Yine de, karakter düzeyinde, eğer bir True değer, dizenin bir sayı içerip içermediğini belirlemek için yeterlidir - uygulanabilir.

isnumeric() ve isdigit() Arasındaki Fark?

Öyleyse, arasındaki fark nedir isnumeric() ve isdigit()? Biz varken - peki ya isdecimal()?

  • isnumeric() herhangi bir karakterin olup olmadığını kontrol eder unicode gösterimi bir bölgesinin Sayısal değer (romen sayısal gösterimleri, üst simgeler, alt simgeler ve kesirler içerir)
  • isdigit() herhangi bir karakterin olup olmadığını kontrol eder unicode rakam (romen sayısal gösterimleri içermez, ancak süper/alt simgeler ve kesirler içerir)
  • isdecimal() herhangi bir karakterin olup olmadığını kontrol eder ondalık basamak (geri dönecek olan False olmayan her şey için 0..9 10 tabanında)

isnumeric() en geniş yöntemdir, isdecimal() üçü arasında en dar olanıdır.

Dizenin Sayı İçerip İçermediğini map() ve any() ile kontrol edin

The map() işlevi, harita işlevinde geçirilen yinelemenin her öğesi için sağlanan işlevi yürütür. Bir yinelemenin her öğesi, işleve bir parametre olarak iletilir:

map(function, iterable)

The function her öğe için yürütülür iterable. Bu, çok esnek ve güçlü bir mantığa izin verir, yalnızca kapsamın genişliğiyle sınırlıdır. function girişi arayın! Yöntem bir döndürür map liste veya küme gibi diğer koleksiyonlara kolayca dönüştürülebilen örnek.

Bir karakterin sayı olup olmadığını temsil eden bir boole döndüren bir işlev yazabiliriz ve map() çağrısı böylece bir boole değerleri listesiyle sonuçlanacaktır.

The any() İade True geçirilen yinelemenin herhangi bir öğesi ise True, aksi halde döndürür False.

Bu ikisini birbirine dizerek – yüksek seviyeli, kısa bir komut dosyası oluşturabilir ve for döngüsünü soyutlayabiliriz:

def func(ch):
    return ch.isdigit() 

input_string = "My name is Satyam & I am 22 yrs old"
contains_number = any(list(map(func, input_string)))
print("Is there a number present?", contains_number)

Bunun sonucu:

Is there a number present? True

İşleviniz tek satırlık ise, onu adlandırılmış bir işlev olarak çıkarmaya gerek yoktur. Anonim yazabilirsin lambda işlevi bunun yerine kısalık uğruna:

En iyi uygulamalar, endüstri tarafından kabul edilen standartlar ve dahil edilen hile sayfası ile Git'i öğrenmek için uygulamalı, pratik kılavuzumuza göz atın. Googling Git komutlarını durdurun ve aslında öğrenmek o!

input_string = "My name is Satyam & I am 22 yrs old"
contains_number = any(list(map(lambda ch: ch.isdigit(), input_string)))
print("Is there any number present?", contains_number)

Bu ayrıca aşağıdakilerle de sonuçlanır:

Is there any number present? True

String'in Python'da Normal İfadelerle Sayı İçerip İçermediğini Kontrol Edin

Normal İfadeler arama kalıpları giriş metniyle eşleşecek şekilde tasarlanmıştır. Esnektirler ve doğası gereği aranacak aynı model için istediğiniz sayıda ifade yazabilir ve aklınıza gelebilecek herhangi bir izlenebilir modeli kapsayabilirsiniz.

Python'un re modül, metni normal ifadelere göre yazmak, derlemek ve eşleştirmek için kullanılır. Gibi çeşitli yöntemleri ortaya çıkarır. match() bir dizenin bir kalıpla başlayıp başlamadığıyla eşleşen, search() bu, bir dizideki muhtemelen birçok eşleşmenin ilk oluşumunu bulur ve findall() tüm oluşumları denetler.

Not: Her üç yöntem de kabul eder pattern ve search bağımsız değişken ve için bir arama çalıştırın pattern içinde search dize.

Bir şeyi tanımlayan model basamak is "d+":

import re
input_string = "My name is Satyam & I am 22 yrs old"
match = re.search(r"d+", input_string)
if match:
    print("Is there any number present?", "Yes")
else:
    print("Is there any number present?", "No")

The search() yöntem bir re.Match bulunan eşleşmeyi ve başlangıç ​​ve bitiş indekslerini içeren nesne:


Nesne, bir olup olmadığına bağlı olarak bir boole değeriyle değerlendirilebilir. re.Match nesne veya None. Bunun sonucunda:

Is there any number present? Yes

Aksine search() Yöntem, findall() yöntem, yalnızca ilki yerine modelin tüm oluşumlarını döndürür:

import re
input_string = "My name is Satyam & I am 22 yrs old"
match = re.findall(r"d+", input_string)
if match:
    print("Is there any number present?", "Yes")
else:
    print("Is there any number present?", "No")

Bunun sonucu:

Is there any number present? Yes

Kıyaslama

Peki ya performans? Yöntemleri yalnızca sonucu döndürmekle sınırlayarak mantığı çıkarır ve gereksiz parçaları kırparsanız, aynı girdi üzerinde bunları kolayca birbiriyle karşılaştırabilirsiniz:

%timeit ord_check()
%timeit isnumeric_check()
%timeit is_digit_check()
%timeit lambda_check()
%timeit regex_check()

Bunun sonucu:

2.18 µs ± 51.5 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
2.04 µs ± 639 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
1.88 µs ± 448 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
5.07 µs ± 915 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
1.47 µs ± 3.41 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

Genel olarak for-loop yaklaşımları, belirli yöntemlerden çok az ek yük ile yaklaşık olarak aynı zamanda çalışır. Lambda ile any() varsayılan olarak en yavaş olanıdır (bir listeyi bir listeye dönüştürüp ardından onu küçülttüğü için birçok gereksiz işlem), Normal İfadeler ise etrafındaki en düşük varyansla en hızlı çalışma zamanına sahiptir (sürekli olarak hızlıdırlar).

Bununla birlikte, daha uzun giriş metinlerinde, özellikle eşleşen basamak sayısına bağlı olarak (rakamların ortak olup olmadığına bakılmaksızın) farklı yaklaşımların her birindeki zaman karmaşıklıkları vurgulanır:

import random
import string

input_string_random = ''.join(random.choices(string.ascii_uppercase + string.digits, k=1000))
print(input_string_random) 

input_string_with_single_digit = ''.join(random.choices(string.ascii_uppercase, k=1000)) + '1'
print(input_string_with_single_digit) 

İlk dize, yaklaşık olarak eşit sayıda basamak ve karakter içeren rastgele bir dizi oluştururken, ikincisi, sonunda tek bir basamak bulunan yalnızca karakter dizisidir (en kötü zaman karmaşıklığı):

%timeit ord_check(input_string_random)
504 ns ± 22.6 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
%timeit ord_check(input_string_with_single_digit)
76.2 µs ± 1.36 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit isnumeric_check(input_string_random)
756 ns ± 170 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
%timeit isnumeric_check(input_string_with_single_digit)
76.2 µs ± 8.43 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit is_digit_check(input_string_random)
549 ns ± 102 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
%timeit is_digit_check(input_string_with_single_digit)
65 µs ± 20.6 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit lambda_check(input_string_random)
114 µs ± 8.77 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit lambda_check(input_string_with_single_digit)
119 µs ± 6.23 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit regex_check(input_string_random)
996 ns ± 19.8 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
%timeit regex_check(input_string_with_single_digit)
22.2 µs ± 1.77 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

Düşük isabet sayısıyla – Normal İfadeler en yüksek performansı gösterenlerdir. Birçok isabetle, lambda fonksiyonu yaklaşımı en performanslı olanıdır ve zaman karmaşıklığını korur girişin çok sayıda veya bir isabet içermesinden bağımsız olarak. Ana dezavantajı (isabet oranı düşük olduğunda yedekli hesaplama), artıklık onu girdiye dayanıklı hale getirdiği için ana gücüne dönüştürülür.

Sonuç

Bu eğitimde, Python'da bir dizgenin en az bir karakter içerip içermediğini kontrol etmenin birçok yolunu inceledik. şuna bir göz attık ord(), isnumeric(), isdigit() ve isdecimal() işlevinin yanı sıra bu mantığı kullanarak bir lambda işlev çağrısı ile nasıl soyutlanacağı map() ve any(). Daha sonra, Normal İfadeleri inceledik ve farklı girdilerle yaklaşımları karşılaştırdık.

Zaman Damgası:

Den fazla Yığın kötüye kullanımı