Python で文字列に数値が含まれているかどうかを確認する

概要

ユーザー入力の検証スクリプトを作成する場合や、ユーザーにパスワードに文字を含めるよう要求するログイン フォームを作成する場合など、文字列に文字が含まれているかどうかを確認する操作は珍しいことではありません。

このチュートリアルでは、Python で文字列に数字/数字が含まれているかどうかを確認する多くの方法を見ていきます。最後に、最も効率的なアプローチのベンチマークを示します。

Python で文字列に数値が含まれているかどうかを確認する

かどうかを確認するには、複数の方法があります。 文字 は数字です (ord(), isnumeric(), isdigit()) を for ループと組み合わせて、少なくとも XNUMX つのポジティブ ヒットをチェックできます。 または、正規表現を一般的なパターン マッチャーとして使用することもできます。これは、柔軟で強力で、大量のテキストに適用できるように設計されています。 最後に–いつでもできます map() 条件文を与えられた各文字、および戻り値 True is any() それらの結果は True.

これらのいずれかを選択する場合は、メソッドの効率、冗長性、コーディング スタイル、および操作に関連する上流または下流のタスクを考慮する必要があります。

ord() を使用して文字列に数値が含まれているかどうかを確認する

  ord() 関数は文字を受け取り、その文字を返します ASCII 値:

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

の ASCII 値 0 は 48 で、ASCII 値は 9 は 57 です。これらの間の任意の数は、拡張により、 ASCII 値が 48 から 57 の間である. 文字列に数字が含まれているかどうかを確認するために、入力文字列全体をトラバースし、各文字の ASCII 値を確認します。ASCII 値が 47 より大きく 58 より小さい場合は、それが数字であることを意味し、次を返します。 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.")

この結果:

Yes, the string contains a number.

文字列に数値が含まれているかどうかを isnumeric() で確認する

  isnumeric() 関数が返す True 入力文字列に数字のみが含まれる場合、それ以外の場合は戻ります 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())

この結果:

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

注:   isnumeric() 関数は期待どおりに動作しません 負数または浮動小数点数. 負数または浮動小数点数のみの文字列を渡すと、返されます Falseなぜなら、 - & . 負の数と浮動小数に関連付けられた文字は、実際には数ではありません。

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

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

ただし、Python では文字は長さ 1 の単なる文字列であるため、文字を反復して使用できます。 isnumeric() それらが数値であるかどうかを確認するには:

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

文字列に数値が含まれているかどうかを isdigit() で確認する

  isdigit() 関数は、文字列内のすべての文字が数字かどうかをチェックします。 はいの場合 - 戻ります True、そうでない場合は戻ります False. 繰り返しますが、Python では文字は長さ 1 の単なる文字列であるため、このメソッドは文字ごとにループで使用できます。

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

注:   isdigit() メソッドは、と同じ方法でのみ動作します isnumeric()、浮動小数点数または負の数を含む文字列を渡すと、 False 特殊文字が数字ではないために返されます。 ただし、キャラクターレベルでは、 True value は、文字列に数字が含まれているかどうかを判断するのに十分です – それは適用可能です.

isnumeric() と isdigit() の違いは?

だから、違いは何ですか isnumeric() & isdigit()? 私たちがそれに取り組んでいる間–どうですか isdecimal()?

  • isnumeric() 任意の文字が ユニコード表現数値 (ローマ数字表現、上付き文字、下付き文字、分数を含む)
  • isdigit() 任意の文字が ユニコード数字 (ローマ数字表現は含まれませんが、上付き/下付き文字と分数は含まれます)
  • isdecimal() 文字が XNUMX進数 (これは戻ります False そうではないもののために 0..9 10進数)

isnumeric() が最も幅広い方法ですが、 isdecimal() XNUMXつの中で最も狭いです。

map() と any() を使用して、文字列に数値が含まれているかどうかを確認します

  map() 関数は、マップ関数で渡された iterable の各要素に対して提供された関数を実行します。 iterable の各要素は、パラメーターとして関数に渡されます。

map(function, iterable)

  function のすべてのアイテムに対して実行されます iterable. これにより、非常に柔軟で強力なロジックが可能になります。 function あなたは入力を呼び出します! メソッドは map これは、リストやセットなどの他のコレクションに簡単に変換できます。

文字が数字かどうかを表すブール値を返す関数を書くことができます。 map() したがって、呼び出しはブール値のリストになります。

  any() 収益 True 渡された iterable のいずれかの要素が True、それ以外の場合は返します False.

これら XNUMX つをつなぎ合わせて、高レベルの短いスクリプトを作成し、for ループを抽象化できます。

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)

この結果:

Is there a number present? True

関数がワンライナーの場合、名前付き関数として抽出する必要はありません。 匿名で書ける ラムダ関数 代わりに、簡潔にするために:

ベストプラクティス、業界で認められた標準、および含まれているチートシートを含む、Gitを学習するための実践的で実用的なガイドを確認してください。 グーグルGitコマンドを停止し、実際に 学ぶ それ!

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)

これも結果として:

Is there any number present? True

正規表現を使用して Python で文字列に数値が含まれているかどうかを確認する

正規表現は 検索パターン 入力テキストと照合するように設計されています。 それらは柔軟性があり、その性質を備えています。検索する同じパターンに対して任意の数の式を記述でき、考えられる扱いやすいパターンをすべてカバーできます。

Pythonの re モジュールは、正規表現に対してテキストを記述、コンパイル、および照合するために使用されます。 などのさまざまなメソッドを公開します。 match() 文字列がパターンで始まるかどうかに一致し、 search() 文字列内のおそらく多くの一致の最初の出現を見つけ、 findall() すべての出現をチェックします。

注: XNUMX つの方法はすべて、 pattern & search 引数を検索して、 pattern セクションに search 文字列。

を識別するパターン 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")

  search() メソッドはを返します re.Match 見つかった一致と開始インデックスと終了インデックスを含むオブジェクト:


オブジェクトは、それが re.Match オブジェクトまたは None。 その結果、次のような結果が得られます。

Is there any number present? Yes

異なり、 search() 方法、 findall() メソッドは、最初のパターンだけでなく、パターンのすべての出現を返します。

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

この結果:

Is there any number present? Yes

ベンチマーク

パフォーマンスはどうですか? ロジックを抽出して不要な部分を削除し、メソッドを結果のみを返すように制限すると、同じ入力に対して簡単にベンチマークできます。

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

この結果:

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)

通常、for ループのアプローチはほぼ同時に実行され、特定のメソッドによるオーバーヘッドはほとんどありません。 とのラムダ any() は事実上最も低速です (リストをリストに変換してから縮小するため、多くの冗長な操作が発生します) が、正規表現は実行時間が最も速く、分散が最も小さくなっています (それらは一貫して高速です)。

ただし、より長い入力テキストでは、特に一致する数字の数 (数字が共通かどうか) に応じて、さまざまなアプローチのそれぞれの時間の複雑さが強調されます。

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) 

最初の文字列は、数字と文字の数がほぼ等しいランダムなシーケンスを生成しますが、後者は、最後に XNUMX つの数字を持つ文字のみの文字列です (最悪の時間の複雑さ):

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

ヒット数が少ない場合 – 正規表現が最もパフォーマンスが高くなります。 ヒット数が多い場合、ラムダ関数アプローチが最もパフォーマンスが高く、 時間の複雑さを保持 入力のヒット数が多いか XNUMX つかに関係なく。 主な欠点 (ヒット率が低い場合の冗長な計算) は、冗長性が入力に対して堅牢であるため、主な強みになります。

まとめ

このチュートリアルでは、Python の文字列に少なくとも XNUMX 文字が含まれているかどうかを確認する複数の方法を調べました。 私たちは、 ord(), isnumeric(), isdigit() & isdecimal() 関数、およびを使用してラムダ関数呼び出しでこのロジックを抽象化する方法 map() & any(). 次に、正規表現を調査し、さまざまな入力を使用してアプローチのベンチマークを行いました。

タイムスタンプ:

より多くの スタックアバス