파이썬에서 문자열을 숫자로 표현할 수 있는지 확인하는 가장 좋은 방법은 무엇입니까?
현재 내가 가지고 있는 기능은 다음과 같습니다.
def is_number(s): try: float(s) return True except ValueError: return False
추하고 느릴 뿐만 아니라 투박해 보입니다. float
를 호출하는 것이 훨씬 더 나빴기 때문에 더 나은 방법을 찾지 못했습니다.
질문자 :Daniel Goldberg
파이썬에서 문자열을 숫자로 표현할 수 있는지 확인하는 가장 좋은 방법은 무엇입니까?
현재 내가 가지고 있는 기능은 다음과 같습니다.
def is_number(s): try: float(s) return True except ValueError: return False
추하고 느릴 뿐만 아니라 투박해 보입니다. float
를 호출하는 것이 훨씬 더 나빴기 때문에 더 나은 방법을 찾지 못했습니다.
부동 소수점 대신 (양수, 부호 없는) 정수를 구문 분석하려는 경우 문자열 객체에 isdigit()
>>> a = "03523" >>> a.isdigit() True >>> b = "963spam" >>> b.isdigit() False
문자열 메서드 - isdigit()
: Python2 , Python3
유니코드 문자열에도 뭔가가 있는데, 저는 유니코드에 익숙하지 않습니다 - 10진수/10진수
추악하고 느릴 뿐만 아니라
나는 둘 다 이의를 제기할 것이다.
정규식 또는 기타 문자열 구문 분석 방법은 더 추하고 느립니다.
나는 위의 것보다 훨씬 더 빠를 수 있다고 확신하지 않습니다. 함수를 호출하고 반환합니다. Try/Catch는 스택 프레임을 광범위하게 검색하지 않고도 가장 일반적인 예외가 포착되기 때문에 많은 오버헤드를 발생시키지 않습니다.
문제는 모든 숫자 변환 함수에 두 가지 종류의 결과가 있다는 것입니다.
C(예를 들어)는 이 문제를 여러 가지 방법으로 해킹합니다. 파이썬은 그것을 명확하고 명시적으로 제시합니다.
나는 이것을하기위한 당신의 코드가 완벽하다고 생각합니다.
TL;DR 가장 좋은 솔루션은 s.replace('.','',1).isdigit()
다양한 접근 방식을 비교하는 몇 가지 벤치마크를 수행했습니다.
def is_number_tryexcept(s): """ Returns True is string is a number. """ try: float(s) return True except ValueError: return False import re def is_number_regex(s): """ Returns True is string is a number. """ if re.match("^\d+?\.\d+?$", s) is None: return s.isdigit() return True def is_number_repl_isdigit(s): """ Returns True is string is a number. """ return s.replace('.','',1).isdigit()
문자열이 숫자가 아니면 예외 블록이 매우 느립니다. 그러나 더 중요한 것은 try-except 방법이 과학적 표기법을 올바르게 처리하는 유일한 접근 방식이라는 것입니다.
funcs = [ is_number_tryexcept, is_number_regex, is_number_repl_isdigit ] a_float = '.1234' print('Float notation ".1234" is not supported by:') for f in funcs: if not f(a_float): print('\t -', f.__name__)
부동 표기법 ".1234"는 다음에서 지원되지 않습니다.
- is_number_regex
scientific1 = '1.000000e+50' scientific2 = '1e50' print('Scientific notation "1.000000e+50" is not supported by:') for f in funcs: if not f(scientific1): print('\t -', f.__name__) print('Scientific notation "1e50" is not supported by:') for f in funcs: if not f(scientific2): print('\t -', f.__name__)
과학적 표기법 "1.000000e+50"은 다음에서 지원되지 않습니다.
- is_number_regex
- is_number_repl_isdigit
과학적 표기법 "1e50"은 다음에서 지원되지 않습니다.
- is_number_regex
- is_number_repl_isdigit
import timeit test_cases = ['1.12345', '1.12.345', 'abc12345', '12345'] times_n = {f.__name__:[] for f in funcs} for t in test_cases: for f in funcs: f = f.__name__ times_n[f].append(min(timeit.Timer('%s(t)' %f, 'from __main__ import %s, t' %f) .repeat(repeat=3, number=1000000)))
다음 기능이 테스트된 곳
from re import match as re_match from re import compile as re_compile def is_number_tryexcept(s): """ Returns True is string is a number. """ try: float(s) return True except ValueError: return False def is_number_regex(s): """ Returns True is string is a number. """ if re_match("^\d+?\.\d+?$", s) is None: return s.isdigit() return True comp = re_compile("^\d+?\.\d+?$") def compiled_regex(s): """ Returns True is string is a number. """ if comp.match(s) is None: return s.isdigit() return True def is_number_repl_isdigit(s): """ Returns True is string is a number. """ return s.replace('.','',1).isdigit()
고려해야 할 한 가지 예외가 있습니다. 문자열 'NaN'
is_number가 'NaN'에 대해 FALSE를 반환하도록 하려면 Python이 숫자가 아닌 숫자 표현으로 변환하므로 이 코드는 작동하지 않습니다(신원 문제에 대해 이야기):
>>> float('NaN') nan
그렇지 않으면 지금 내가 광범위하게 사용하는 코드 조각에 대해 실제로 감사해야 합니다. :)
NS.
이것은 어떤가요:
'3.14'.replace('.','',1).isdigit()
'.'가 하나 또는 없는 경우에만 true를 반환합니다. 숫자 문자열에서.
'3.14.5'.replace('.','',1).isdigit()
거짓을 반환합니다
편집: 방금 다른 댓글을 보았습니다... .replace(badstuff,'',maxnum_badstuff)
를 추가할 수 있습니다. 임의의 조미료가 아닌 소금을 전달하는 경우(ref: xkcd#974 ) 괜찮을 것입니다 :P
Alfe가 복잡한 핸들을 둘 다 다루기 때문에 float를 별도로 확인할 필요가 없다고 지적한 후 업데이트되었습니다.
def is_number(s): try: complex(s) # for int, long, float and complex except ValueError: return False return True
이전에 언급한 내용: 소수의 경우 실수로 나타낼 수 없는 복소수(예: 1+2i)도 확인해야 할 수 있습니다.
def is_number(s): try: float(s) # for int, long and float except ValueError: try: complex(s) # for complex except ValueError: return False return True
추하고 느릴 뿐만 아니라 투박해 보입니다.
익숙해지는 데 시간이 걸릴 수 있지만 이것이 파이썬적인 방법입니다. 이미 지적했듯이 대안은 더 나쁩니다. 그러나 이런 식으로 일을 하면 또 다른 이점이 있습니다. 바로 다형성입니다.
오리 타이핑의 핵심 아이디어는 "오리처럼 걷고 말하면 오리입니다." 부동 소수점으로 변환할 수 있는지 여부를 결정하는 방법을 변경할 수 있도록 문자열을 하위 클래스화해야 한다고 결정하면 어떻게 될까요? 또는 다른 개체를 완전히 테스트하기로 결정했다면 어떻게 하시겠습니까? 위의 코드를 변경하지 않고도 이러한 작업을 수행할 수 있습니다.
다른 언어는 인터페이스를 사용하여 이러한 문제를 해결합니다. 다른 스레드에 더 나은 솔루션에 대한 분석을 저장하겠습니다. 하지만 요점은 파이썬이 확실히 방정식의 오리 타이핑 측면에 있다는 것이고, 파이썬에서 많은 프로그래밍을 할 계획이라면 아마도 이와 같은 구문에 익숙해져야 할 것입니다. 당신은 물론 그것을 좋아해야합니다).
고려해야 할 또 다른 사항: Python은 다른 많은 언어(예: .Net보다 30배 빠름)에 비해 예외를 던지고 잡는 면에서 매우 빠릅니다. 젠장, 언어 자체는 예외가 아닌 정상적인 프로그램 조건(for 루프를 사용할 때마다)을 전달하기 위해 예외를 던집니다. 따라서 심각한 문제를 발견할 때까지 이 코드의 성능 측면에 대해 너무 많이 걱정하지 않을 것입니다.
int
경우 다음을 사용하십시오.
>>> "1221323".isdigit() True
그러나 float
경우 몇 가지 트릭이 필요합니다 ;-). 모든 float 숫자에는 하나의 점이 있습니다 ...
>>> "12.34".isdigit() False >>> "12.34".replace('.','',1).isdigit() True >>> "12.3.4".replace('.','',1).isdigit() False
또한 음수의 경우 lstrip()
추가하십시오.
>>> '-12'.lstrip('-') '12'
이제 우리는 보편적 인 방법을 얻습니다.
>>> '-12.34'.lstrip('-').replace('.','',1).isdigit() True >>> '.-234'.lstrip('-').replace('.','',1).isdigit() False
이 답변은 다음과 같은 문자열을 찾는 예제가 포함된 단계별 가이드를 제공합니다.
주어진 문자열이 양의 정수 str.isdigit()
을 사용할 수 있습니다.
샘플 결과:
# For digit >>> '1'.isdigit() True >>> '1'.isalpha() False
str.isdigit()
은 문자열이 음수 또는 부동 소수점 수인 False
반환합니다. 예를 들어:
# returns `False` for float >>> '123.3'.isdigit() False # returns `False` for negative number >>> '-123'.isdigit() False
음의 정수와 float
도 확인하려면 다음과 같이 확인하는 사용자 정의 함수를 작성할 수 있습니다.
def is_number(n): try: float(n) # Type-casting the string to `float`. # If string is not a valid `float`, # it'll raise `ValueError` exception except ValueError: return False return True
샘플 실행:
>>> is_number('123') # positive integer number True >>> is_number('123.4') # positive float number True >>> is_number('-123') # negative integer number True >>> is_number('-123.4') # negative `float` number True >>> is_number('abc') # `False` for "some random" string False
위의 함수는 True
를 반환합니다. Python의 경우 숫자가 아님을 나타내는 유효한 부동 소수점이기 때문입니다. 예를 들어:
>>> is_number('NaN') True
숫자가 "NaN"인지 확인하기 위해 math.isnan()
을 다음과 같이 사용할 수 있습니다.
>>> import math >>> nan_num = float('nan') >>> math.isnan(nan_num) True
또는 이를 확인하기 위해 추가 라이브러리를 가져오지 않으려면 ==
사용하여 라이브러리를 자체와 비교하여 간단히 확인할 수 있습니다. Python은 nan
float가 자신과 비교될 때 False
예를 들어:
# `nan_num` variable is taken from above example >>> nan_num == nan_num False
따라서 위의 함수 is_number
"NaN"
대해 False
를 반환하도록 업데이트할 수 있습니다 .
def is_number(n): is_number = True try: num = float(n) # check for "nan" floats is_number = num == num # or use `math.isnan(num)` except ValueError: is_number = False return is_number
샘플 실행:
>>> is_number('Nan') # not a number "Nan" string False >>> is_number('nan') # not a number string "nan" with all lower cased False >>> is_number('123') # positive integer True >>> is_number('-123') # negative integer True >>> is_number('-1.12') # negative `float` True >>> is_number('abc') # "some random" string False
추신: 번호 유형에 따라 각 검사에 대한 각 작업에는 추가 오버헤드가 있습니다. 요구 사항에 맞는 is_number
함수의 버전을 선택하십시오.
숫자가 아닌 문자열의 경우 try: except:
는 실제로 정규식보다 느립니다. 유효한 숫자 문자열의 경우 정규식이 더 느립니다. 따라서 적절한 방법은 입력에 따라 다릅니다.
당신이 성능 바인드에 있다는 것을 발견하면, 당신은 새로운 서드 파티 모듈을 호출 사용할 수 있습니다 fastnumbers 라는 기능을 제공isfloat을 . 전체 공개, 나는 저자입니다. 나는 그 결과를 아래의 타이밍에 포함시켰다.
from __future__ import print_function import timeit prep_base = '''\ x = 'invalid' y = '5402' z = '4.754e3' ''' prep_try_method = '''\ def is_number_try(val): try: float(val) return True except ValueError: return False ''' prep_re_method = '''\ import re float_match = re.compile(r'[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?$').match def is_number_re(val): return bool(float_match(val)) ''' fn_method = '''\ from fastnumbers import isfloat ''' print('Try with non-number strings', timeit.timeit('is_number_try(x)', prep_base + prep_try_method), 'seconds') print('Try with integer strings', timeit.timeit('is_number_try(y)', prep_base + prep_try_method), 'seconds') print('Try with float strings', timeit.timeit('is_number_try(z)', prep_base + prep_try_method), 'seconds') print() print('Regex with non-number strings', timeit.timeit('is_number_re(x)', prep_base + prep_re_method), 'seconds') print('Regex with integer strings', timeit.timeit('is_number_re(y)', prep_base + prep_re_method), 'seconds') print('Regex with float strings', timeit.timeit('is_number_re(z)', prep_base + prep_re_method), 'seconds') print() print('fastnumbers with non-number strings', timeit.timeit('isfloat(x)', prep_base + 'from fastnumbers import isfloat'), 'seconds') print('fastnumbers with integer strings', timeit.timeit('isfloat(y)', prep_base + 'from fastnumbers import isfloat'), 'seconds') print('fastnumbers with float strings', timeit.timeit('isfloat(z)', prep_base + 'from fastnumbers import isfloat'), 'seconds') print()
Try with non-number strings 2.39108395576 seconds Try with integer strings 0.375686168671 seconds Try with float strings 0.369210958481 seconds Regex with non-number strings 0.748660802841 seconds Regex with integer strings 1.02021503448 seconds Regex with float strings 1.08564686775 seconds fastnumbers with non-number strings 0.174362897873 seconds fastnumbers with integer strings 0.179651021957 seconds fastnumbers with float strings 0.20222902298 seconds
보시다시피
try: except:
숫자 입력의 경우 빠르지만 잘못된 입력의 경우 매우 느림fastnumbers
는 두 경우 모두에서 승리합니다.C#에는 스칼라 값의 구문 분석을 처리하는 두 가지 다른 함수가 있습니다.
float.parse():
def parse(string): try: return float(string) except Exception: throw TypeError
참고: 예외를 TypeError로 변경한 이유가 궁금하다면 여기에 설명서가 있습니다.
float.try_parse():
def try_parse(string, fail=None): try: return float(string) except Exception: return fail;
참고: 여전히 값 유형이기 때문에 부울 'False'를 반환하고 싶지 않습니다. 실패를 나타내기 때문에 아무 것도 좋지 않습니다. 물론 다른 것을 원하면 fail 매개변수를 원하는 대로 변경할 수 있습니다.
float를 확장하여 'parse()' 및 'try_parse()'를 포함하려면 이러한 메서드를 추가하기 위해 'float' 클래스를 원숭이 패치해야 합니다.
기존 기능을 존중하려면 코드가 다음과 같아야 합니다.
def monkey_patch(): if(!hasattr(float, 'parse')): float.parse = parse if(!hasattr(float, 'try_parse')): float.try_parse = try_parse
SideNote: 저는 개인적으로 Monkey Punching이라고 부르는 것을 선호합니다. YMMV가 아닌 이 작업을 할 때 언어를 남용하는 것처럼 느껴지기 때문입니다.
용법:
float.parse('giggity') // throws TypeException float.parse('54.3') // returns the scalar value 54.3 float.tryParse('twank') // returns None float.tryParse('32.2') // returns the scalar value 32.2
그리고 위대한 현자 Pythonas는 교황청 Sharpisus에게 말했다, "당신이 할 수 있는 것은 무엇이든 내가 더 잘할 수 있습니다. 나는 당신보다 더 잘할 수 있습니다."
나는 이것이 특히 오래되었다는 것을 알고 있지만 이것을 찾는 누구에게나 매우 가치가있을 수있는 가장 많이 투표 된 답변에서 누락 된 정보를 다루는 답변을 추가 할 것입니다.
다음 각 방법에 대해 입력을 수락해야 하는 경우 개수와 연결합니다. (0-255 등이 아닌 정수의 음성 정의를 사용한다고 가정)
x.isdigit()
은 x가 정수인지 확인하는 데 적합합니다.
x.replace('-','').isdigit()
은 x가 음수인지 확인하는 데 잘 작동합니다.(확인 - 첫 번째 위치에서)
x.replace('.','').isdigit()
x가 십진수인지 확인하는 데 잘 작동합니다.
x.replace(':','').isdigit()
x가 비율인지 확인하는 데 잘 작동합니다.
x.replace('/','',1).isdigit()
x가 분수인지 확인하는 데 잘 작동합니다.
float() 가 특별히 그런 용도로 사용되었기 때문에 float() 로 캐스팅하고 ValueError 를 잡는 것이 가장 빠른 방법일 것입니다. 문자열 구문 분석(정규식 등)이 필요한 다른 항목은 이 작업에 맞게 조정되지 않았기 때문에 속도가 느릴 수 있습니다. 내 $0.02.
유니코드 문자열을 사용할 수 있습니다. 원하는 대로 수행할 수 있는 방법이 있습니다.
>>> s = u"345" >>> s.isnumeric() True
또는:
>>> s = "345" >>> u = unicode(s) >>> u.isnumeric() True
따라서 모든 것을 종합하면 Nan, 무한대 및 복소수(i가 아닌 j로 지정되는 것처럼 보임)를 확인하면 다음과 같은 결과가 나타납니다.
def is_number(s): try: n=str(float(s)) if n == "nan" or n=="inf" or n=="-inf" : return False except ValueError: try: complex(s) # for complex except ValueError: return False return True
어떤 방법이 가장 빠른지 알고 싶었습니다. 전반적으로 가장 우수하고 일관된 결과가 check_replace
함수에 의해 제공되었습니다. 가장 빠른 결과는 check_exception
함수에 의해 제공되었지만 예외가 발생하지 않은 경우에만 해당 코드가 가장 효율적이지만 예외를 던지는 오버헤드가 상당히 큽니다.
성공적인 캐스트를 확인하는 것이 정확한 유일한 방법입니다. 예를 들어 이것은 check_exception
과 함께 작동하지만 다른 두 테스트 함수는 유효한 부동 소수점에 대해 False를 반환합니다.
huge_number = float('1e+100')
다음은 벤치마크 코드입니다.
import time, re, random, string ITERATIONS = 10000000 class Timer: def __enter__(self): self.start = time.clock() return self def __exit__(self, *args): self.end = time.clock() self.interval = self.end - self.start def check_regexp(x): return re.compile("^\d*\.?\d*$").match(x) is not None def check_replace(x): return x.replace('.','',1).isdigit() def check_exception(s): try: float(s) return True except ValueError: return False to_check = [check_regexp, check_replace, check_exception] print('preparing data...') good_numbers = [ str(random.random() / random.random()) for x in range(ITERATIONS)] bad_numbers = ['.' + x for x in good_numbers] strings = [ ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(random.randint(1,10))) for x in range(ITERATIONS)] print('running test...') for func in to_check: with Timer() as t: for x in good_numbers: res = func(x) print('%s with good floats: %s' % (func.__name__, t.interval)) with Timer() as t: for x in bad_numbers: res = func(x) print('%s with bad floats: %s' % (func.__name__, t.interval)) with Timer() as t: for x in strings: res = func(x) print('%s with strings: %s' % (func.__name__, t.interval))
다음은 2017 MacBook Pro 13에서 Python 2.7.10을 사용한 결과입니다.
check_regexp with good floats: 12.688639 check_regexp with bad floats: 11.624862 check_regexp with strings: 11.349414 check_replace with good floats: 4.419841 check_replace with bad floats: 4.294909 check_replace with strings: 4.086358 check_exception with good floats: 3.276668 check_exception with bad floats: 13.843092 check_exception with strings: 15.786169
다음은 2017 MacBook Pro 13에서 Python 3.6.5를 사용한 결과입니다.
check_regexp with good floats: 13.472906000000009 check_regexp with bad floats: 12.977665000000016 check_regexp with strings: 12.417542999999995 check_replace with good floats: 6.011045999999993 check_replace with bad floats: 4.849356 check_replace with strings: 4.282754000000011 check_exception with good floats: 6.039081999999979 check_exception with bad floats: 9.322753000000006 check_exception with strings: 9.952595000000002
다음은 2017 MacBook Pro 13에서 PyPy 2.7.13을 사용한 결과입니다.
check_regexp with good floats: 2.693217 check_regexp with bad floats: 2.744819 check_regexp with strings: 2.532414 check_replace with good floats: 0.604367 check_replace with bad floats: 0.538169 check_replace with strings: 0.598664 check_exception with good floats: 1.944103 check_exception with bad floats: 2.449182 check_exception with strings: 2.200056
입력은 다음과 같을 수 있습니다.
a="50"
b=50
c=50.1
d="50.1"
이 함수의 입력은 모든 것이 될 수 있습니다!
주어진 변수가 숫자인지 여부를 찾습니다. 숫자 문자열은 선택적 기호, 임의의 자릿수, 선택적 소수점 부분 및 선택적 지수 부분으로 구성됩니다. 따라서 +0123.45e6은 유효한 숫자 값입니다. 16진수(예: 0xf4c3b00c) 및 이진수(예: 0b10100111001) 표기법은 허용되지 않습니다.
is_numeric 함수
import ast import numbers def is_numeric(obj): if isinstance(obj, numbers.Number): return True elif isinstance(obj, str): nodes = list(ast.walk(ast.parse(obj)))[1:] if not isinstance(nodes[0], ast.Expr): return False if not isinstance(nodes[-1], ast.Num): return False nodes = nodes[1:-1] for i in range(len(nodes)): #if used + or - in digit : if i % 2 == 0: if not isinstance(nodes[i], ast.UnaryOp): return False else: if not isinstance(nodes[i], (ast.USub, ast.UAdd)): return False return True else: return False
시험:
>>> is_numeric("54") True >>> is_numeric("54.545") True >>> is_numeric("0x45") True
is_float 함수
주어진 변수가 float인지 여부를 찾습니다. float 문자열은 선택적 기호, 임의의 숫자, ...
import ast def is_float(obj): if isinstance(obj, float): return True if isinstance(obj, int): return False elif isinstance(obj, str): nodes = list(ast.walk(ast.parse(obj)))[1:] if not isinstance(nodes[0], ast.Expr): return False if not isinstance(nodes[-1], ast.Num): return False if not isinstance(nodes[-1].n, float): return False nodes = nodes[1:-1] for i in range(len(nodes)): if i % 2 == 0: if not isinstance(nodes[i], ast.UnaryOp): return False else: if not isinstance(nodes[i], (ast.USub, ast.UAdd)): return False return True else: return False
시험:
>>> is_float("5.4") True >>> is_float("5") False >>> is_float(5) False >>> is_float("5") False >>> is_float("+5.4") True
ast 는 무엇입니까?
str.isdigit() 메서드 사용
>>> a=454 >>> a.isdigit() Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'int' object has no attribute 'isdigit' >>> a="454" >>> a.isdigit() True
정수 값 감지:
>>> isinstance("54", int) False >>> isinstance(54, int) True >>>
부동 소수점 감지:
>>> isinstance("45.1", float) False >>> isinstance(45.1, float) True
문자열의 모든 문자가 숫자이고 하나 이상의 문자가 있으면
True
반환False
반환합니다. 숫자 문자에는 숫자 문자와 유니코드 숫자 값 속성이 있는 모든 문자(예: U+2155, VULGAR FRACTION ONE FIFTH)가 포함됩니다. 공식적으로 숫자는 속성 값이 Numeric_Type=Digit, Numeric_Type=Decimal 또는 Numeric_Type=Numeric인 문자입니다.
문자열의 모든 문자가 10진수 문자이고 하나 이상의 문자가 있으면
True
반환False
반환합니다. 10진수 문자는 10진수로 숫자를 구성하는 데 사용할 수 있는 문자입니다(예: U+0660, ARABIC-INDIC DIGIT ZERO). 공식적으로 10진수 문자는 유니코드 일반 범주 "Nd"의 문자입니다.
둘 다 Python 3.0의 문자열 유형에 사용할 수 있습니다.
나는 당신의 솔루션 괜찮 생각하지만, 올바른 정규 표현식 구현이있다.
정당하지 않다고 생각하는 이러한 답변에 대한 정규 표현식 증오가 많은 것 같습니다. 정규 표현식은 합리적으로 깨끗하고 정확하며 빠를 수 있습니다. 그것은 당신이 무엇을하려고하는지에 달려 있습니다. 원래 질문은 "문자열을 숫자(부동 소수점)로 표현할 수 있는지 확인"하는 방법이었습니다(제목에 따라). 아마도 당신은 그것이 유효한지 확인한 후에 숫자/부동수 값을 사용하기를 원할 것입니다. 그러나 어떤 이유로 문자열 이 숫자 인지 확인하려는 경우 정규식도 제대로 작동하지만 올바르게 수행하기는 어렵습니다. 예를 들어 지금까지 대부분의 정규식 답변은 파이썬에 관한 한 float인 정수 부분(예: ".7")이 없는 문자열을 적절하게 구문 분석하지 않는다고 생각합니다. 그리고 분수 부분이 필요하지 않은 단일 정규식에서 확인하기가 약간 까다롭습니다. 이것을 보여주기 위해 두 개의 정규식을 포함했습니다.
그것은 "숫자"가 무엇인지에 대한 흥미로운 질문을 제기합니다. 파이썬에서 float로 유효한 "inf"를 포함합니까? 또는 "숫자"이지만 파이썬으로 표현할 수 없는 숫자(예: float max보다 큰 숫자)를 포함합니까?
숫자를 구문 분석하는 방법에도 모호함이 있습니다. 예를 들어 "--20"은 어떻습니까? 이것은 "숫자"입니까? 이것은 "20"을 나타내는 합법적 인 방법입니까? Python은 "var = --20"을 수행하고 20으로 설정할 수 있도록 합니다(실제로 이것은 표현식으로 취급하기 때문입니다). 그러나 float("--20")은 작동하지 않습니다.
어쨌든, 더 많은 정보가 없으면 여기에 파이썬이 구문 분석할 때 모든 int와 float를 포함한다고 생각하는 정규식이 있습니다.
# Doesn't properly handle floats missing the integer part, such as ".7" SIMPLE_FLOAT_REGEXP = re.compile(r'^[-+]?[0-9]+\.?[0-9]+([eE][-+]?[0-9]+)?$') # Example "-12.34E+56" # sign (-) # integer (12) # mantissa (34) # exponent (E+56) # Should handle all floats FLOAT_REGEXP = re.compile(r'^[-+]?([0-9]+|[0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?$') # Example "-12.34E+56" # sign (-) # integer (12) # OR # int/mantissa (12.34) # exponent (E+56) def is_float(str): return True if FLOAT_REGEXP.match(str) else False
몇 가지 예시적인 테스트 값:
True <- +42 True <- +42.42 False <- +42.42.22 True <- +42.42e22 True <- +42.42E-22 False <- +42.42e-22.8 True <- .42 False <- 42nope
@ron-reiter의 답변 에서 벤치마킹 코드를 실행하면 이 정규식이 실제로 일반 정규식보다 빠르고 예외보다 나쁜 값을 처리하는 데 훨씬 빠릅니다. 이는 의미가 있습니다. 결과:
check_regexp with good floats: 18.001921 check_regexp with bad floats: 17.861423 check_regexp with strings: 17.558862 check_correct_regexp with good floats: 11.04428 check_correct_regexp with bad floats: 8.71211 check_correct_regexp with strings: 8.144161 check_replace with good floats: 6.020597 check_replace with bad floats: 5.343049 check_replace with strings: 5.091642 check_exception with good floats: 5.201605 check_exception with bad floats: 23.921864 check_exception with strings: 23.755481
속도 테스트를 해봤습니다. 문자열이 전략은 문자열 가능성이 숫자로 당신은 정수 검사에 관심이없는 가장 빠른 possible.If이다 제외 / A 번호 시도 할 가능성이있는 경우, 그것은 몇 가지 테스트 (isdigit에 플러스 제목을 할 worths라고하자 '-'). 부동 소수점 수를 확인하려면 이스케이프 없이 try/except 코드를 사용해야 합니다.
문자열이 기본 유형(float, int, str, bool)으로 캐스팅되는지 확인해야 했습니다. 인터넷에서 아무것도 찾지 못한 후 나는 이것을 만들었습니다.
def str_to_type (s): """ Get possible cast type for a string Parameters ---------- s : string Returns ------- float,int,str,bool : type Depending on what it can be cast to """ try: f = float(s) if "." not in s: return int return float except ValueError: value = s.upper() if value == "TRUE" or value == "FALSE": return bool return type(s)
예시
str_to_type("true") # bool str_to_type("6.0") # float str_to_type("6") # int str_to_type("6abc") # str str_to_type(u"6abc") # unicode
유형을 캡처하여 사용할 수 있습니다.
s = "6.0" type_ = str_to_type(s) # float f = type_(s)
RyanN 제안
NaN 및 Inf에 대해 False를 반환하려면 행을 x = float(s); (x == x) 및 (x - 1 != x)를 반환합니다. Inf 및 NaN을 제외한 모든 float에 대해 True를 반환해야 합니다.
x-1 == x
가 true를 반환하기 때문에 이것은 제대로 작동하지 않습니다. 예: 2.0**54 - 1 == 2.0**54
이 코드는 정규식을 사용하지 않고 지수, 부동 소수점 및 정수를 처리합니다.
return True if str1.lstrip('-').replace('.','',1).isdigit() or float(str1) else False
float에 대한 가장 일반적인 경우에는 정수와 소수를 처리하고 싶습니다. 문자열 "1.1"
을 예로 들어 보겠습니다.
다음 중 하나를 시도합니다.
1.> 숫자()
word = "1.1" "".join(word.split(".")).isnumeric() >>> True
2.> isdigit()
word = "1.1" "".join(word.split(".")).isdigit() >>> True
3.> 10 진수()
word = "1.1" "".join(word.split(".")).isdecimal() >>> True
속도:
► 앞서 언급한 모든 방법은 속도가 비슷합니다.
%timeit "".join(word.split(".")).isnumeric() >>> 257 ns ± 12 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) %timeit "".join(word.split(".")).isdigit() >>> 252 ns ± 11 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) %timeit "".join(word.split(".")).isdecimal() >>> 244 ns ± 7.17 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
import re def is_number(num): pattern = re.compile(r'^[-+]?[-0-9]\d*\.\d*|[-+]?\.?[0-9]\d*$') result = pattern.match(num) if result: return True else: return False >>>: is_number('1') True >>>: is_number('111') True >>>: is_number('11.1') True >>>: is_number('-11.1') True >>>: is_number('inf') False >>>: is_number('-inf') False
여기 내 간단한 방법이 있습니다. 일부 문자열을 반복하고 있으며 숫자로 판명되면 배열에 추가하고 싶다고 가정해 보겠습니다.
try: myvar.append( float(string_to_check) ) except: continue
문자열이 숫자로 판명되면 myvar.apppend를 문자열로 수행하려는 작업으로 바꾸십시오. 아이디어는 float() 연산을 사용하고 반환된 오류를 사용하여 문자열이 숫자인지 여부를 결정하는 것입니다.
저는 이 스레드로 이끄는 문제, 즉 데이터 컬렉션을 가장 직관적인 방식으로 문자열과 숫자로 변환하는 방법에 대해 작업하고 있었습니다. 원래 코드를 읽은 후 내가 필요한 것이 두 가지 면에서 다르다는 것을 깨달았습니다.
1 - 문자열이 정수를 나타내는 경우 정수 결과를 원했습니다.
2 - 숫자 또는 문자열 결과가 데이터 구조에 고정되기를 원했습니다.
그래서 이 파생물을 생성하기 위해 원래 코드를 수정했습니다.
def string_or_number(s): try: z = int(s) return z except ValueError: try: z = float(s) return z except ValueError: return s
언급한 기능도 사용했지만 곧 "Nan", "Inf"와 같은 문자열과 그 변형이 숫자로 간주된다는 것을 알 수 있습니다. 따라서 해당 유형의 입력에 대해 false를 반환하고 "1e3" 변형에 실패하지 않는 개선된 기능 버전을 제안합니다.
def is_float(text): try: float(text) # check for nan/infinity etc. if text.isalpha(): return False return True except ValueError: return False
사용자 도우미 기능:
def if_ok(fn, string): try: return fn(string) except Exception as e: return None
그 다음에
if_ok(int, my_str) or if_ok(float, my_str) or if_ok(complex, my_str) is_number = lambda s: any([if_ok(fn, s) for fn in (int, float, complex)])
True 및 False보다 더 유용한 값을 반환하여 예외 기술을 유용한 방식으로 일반화할 수 있습니다. 예를 들어 이 함수는 문자열을 따옴표로 묶지만 숫자는 그대로 둡니다. R에 대한 몇 가지 변수 정의를 만들기 위해 빠르고 더티 필터에 필요한 것입니다.
import sys def fix_quotes(s): try: float(s) return s except ValueError: return '"{0}"'.format(s) for line in sys.stdin: input = line.split() print input[0], '<- c(', ','.join(fix_quotes(c) for c in input[1:]), ')'
출처 : http:www.stackoverflow.com/questions/354038/how-do-i-check-if-a-string-is-a-number-float
두 가지 다른 지점의 파일을 비교하는 방법 (0) | 2022.01.02 |
---|---|
++[[]][+[]]+[+[]]가 문자열 "10"을 반환하는 이유는 무엇입니까? (0) | 2022.01.02 |
JavaScript 객체 배열에서 id로 객체 찾기 (0) | 2022.01.02 |
Java에서 문자열을 분할하는 방법 (0) | 2022.01.02 |
사전에서 요소 삭제 (0) | 2022.01.02 |