문자열 목록을 통해 실행되고 가능한 경우 정수 또는 부동 소수점 숫자로 변환하는 Python 코드가 있습니다. 정수로 이것을하는 것은 매우 쉽습니다.
if element.isdigit():
newelement = int(element)
부동 소수점 숫자는 더 어렵습니다. 지금 partition('.')
은 문자열을 분할하고 한쪽 또는 양쪽이 숫자인지 확인하는 데 사용하고 있습니다.
partition = element.partition('.')
if (partition[0].isdigit() and partition[1] == '.' and partition[2].isdigit())
or (partition[0] == '' and partition[1] == '.' and partition[2].isdigit())
or (partition[0].isdigit() and partition[1] == '.' and partition[2] == ''):
newelement = float(element)
이것은 작동하지만 분명히 if 문은 약간의 곰입니다. 내가 고려한 다른 해결책은 이 질문에 설명 된 것처럼 변환을 try / catch 블록으로 감싸고 성공했는지 확인하는 것 입니다.
다른 아이디어가 있습니까? 파티션 및 시도 / 캐치 접근의 상대적인 장점에 대한 의견?
답변
난 그냥 사용합니다 ..
try:
float(element)
except ValueError:
print "Not a float"
.. 그것은 간단하고 작동합니다
또 다른 옵션은 정규식입니다.
import re
if re.match(r'^-?\d+(?:\.\d+)?$', element) is None:
print "Not float"
답변
float 확인을위한 Python 메소드 :
def isfloat(value):
try:
float(value)
return True
except ValueError:
return False
플로트 보트에 숨어있는 고블린들에게 물지 마세요! 단위 테스트를 수행하십시오!
플로트가 아닌 것은 무엇입니까?
Command to parse Is it a float? Comment
-------------------------------------- --------------- ------------
print(isfloat("")) False
print(isfloat("1234567")) True
print(isfloat("NaN")) True nan is also float
print(isfloat("NaNananana BATMAN")) False
print(isfloat("123.456")) True
print(isfloat("123.E4")) True
print(isfloat(".1")) True
print(isfloat("1,234")) False
print(isfloat("NULL")) False case insensitive
print(isfloat(",1")) False
print(isfloat("123.EE4")) False
print(isfloat("6.523537535629999e-07")) True
print(isfloat("6e777777")) True This is same as Inf
print(isfloat("-iNF")) True
print(isfloat("1.797693e+308")) True
print(isfloat("infinity")) True
print(isfloat("infinity and BEYOND")) False
print(isfloat("12.34.56")) False Two dots not allowed.
print(isfloat("#56")) False
print(isfloat("56%")) False
print(isfloat("0E0")) True
print(isfloat("x86E0")) False
print(isfloat("86-5")) False
print(isfloat("True")) False Boolean is not a float.
print(isfloat(True)) True Boolean is a float
print(isfloat("+1e1^5")) False
print(isfloat("+1e1")) True
print(isfloat("+1e1.3")) False
print(isfloat("+1.3P1")) False
print(isfloat("-+1")) False
print(isfloat("(1)")) False brackets not interpreted
답변
'1.43'.replace('.','',1).isdigit()
true
‘.’가 없거나없는 경우에만 반환 됩니다. 자릿수로.
'1.4.3'.replace('.','',1).isdigit()
돌아올 것이다 false
'1.ww'.replace('.','',1).isdigit()
돌아올 것이다 false
답변
TL; DR :
- 입력이 대부분 float로 변환 될 수 있는 문자열 인 경우이
try: except:
방법이 가장 적합한 기본 Python 방법입니다. - 입력이 대부분 부동 소수점으로 변환 할 수없는 문자열 인 경우 정규식 또는 파티션 방법이 더 좋습니다.
- 1) 입력이 확실하지 않거나 속도가 더 필요하고 2) 타사 C 확장을 신경 쓰지 않고 설치할 수 있으면 빠른 번호 가 매우 잘 작동합니다.
fastnumbers 라는 타사 모듈을 통해 사용할 수있는 다른 방법이 있습니다 (공개, 저는 저자입니다). isfloat 라는 함수를 제공합니다 . 이 답변 에서 Jacob Gabrielson 이 간략하게 설명한 unittest 예제를 취 했지만 fastnumbers.isfloat
방법을 추가했습니다 . 또한 Jacob의 예제는 점 연산자로 인해 전역 조회에 소비 되었기 때문에 정규식 옵션에 대한 정의를 수행하지 않았다는 점에 유의해야합니다 try: except:
.
def is_float_try(str):
try:
float(str)
return True
except ValueError:
return False
import re
_float_regexp = re.compile(r"^[-+]?(?:\b[0-9]+(?:\.[0-9]*)?|\.[0-9]+\b)(?:[eE][-+]?[0-9]+\b)?$").match
def is_float_re(str):
return True if _float_regexp(str) else False
def is_float_partition(element):
partition=element.partition('.')
if (partition[0].isdigit() and partition[1]=='.' and partition[2].isdigit()) or (partition[0]=='' and partition[1]=='.' and partition[2].isdigit()) or (partition[0].isdigit() and partition[1]=='.' and partition[2]==''):
return True
else:
return False
from fastnumbers import isfloat
if __name__ == '__main__':
import unittest
import timeit
class ConvertTests(unittest.TestCase):
def test_re_perf(self):
print
print 're sad:', timeit.Timer('ttest.is_float_re("12.2x")', "import ttest").timeit()
print 're happy:', timeit.Timer('ttest.is_float_re("12.2")', "import ttest").timeit()
def test_try_perf(self):
print
print 'try sad:', timeit.Timer('ttest.is_float_try("12.2x")', "import ttest").timeit()
print 'try happy:', timeit.Timer('ttest.is_float_try("12.2")', "import ttest").timeit()
def test_fn_perf(self):
print
print 'fn sad:', timeit.Timer('ttest.isfloat("12.2x")', "import ttest").timeit()
print 'fn happy:', timeit.Timer('ttest.isfloat("12.2")', "import ttest").timeit()
def test_part_perf(self):
print
print 'part sad:', timeit.Timer('ttest.is_float_partition("12.2x")', "import ttest").timeit()
print 'part happy:', timeit.Timer('ttest.is_float_partition("12.2")', "import ttest").timeit()
unittest.main()
내 컴퓨터에서 출력은 다음과 같습니다.
fn sad: 0.220988988876
fn happy: 0.212214946747
.
part sad: 1.2219619751
part happy: 0.754667043686
.
re sad: 1.50515985489
re happy: 1.01107215881
.
try sad: 2.40243887901
try happy: 0.425730228424
.
----------------------------------------------------------------------
Ran 4 tests in 7.761s
OK
보시다시피, 정규 표현식은 실제로 원래 보이는 것만 큼 나쁘지 않으며, 실제로 속도가 필요한 경우 fastnumbers
방법이 좋습니다.
답변
성능에 관심이 있다면 (그리고 내가 제안하지는 않겠지 만) 시도 기반 접근 방식은 파티션 기반 접근 방식이나 정규 표현식 접근 방식과 비교할 때 확실한 승자가 될 것입니다. 유효하지 않은 문자열.이 경우 잠재적으로 느릴 수 있습니다 (아마 예외 처리 비용으로 인해).
다시 한 번 말하지만, 성능에 신경 쓰지 말고 초당 100 억 번을 수행하는 경우 데이터를 제공하는 것입니다. 또한 파티션 기반 코드는 하나 이상의 유효한 문자열을 처리하지 않습니다.
$ ./floatstr.py 에프.. 슬픈 파티션 : 3.1102449894 행복한 파티션 : 2.09208488464 .. 다시 슬퍼 : 7.76906108856 다시 행복 : 7.09421992302 .. 슬프다 : 12.1525540352 행복해 : 1.44165301323 . ===================================================== ===================== 실패 : test_partition (__ main __. ConvertTests) -------------------------------------------------- -------------------- 역 추적 (가장 최근 통화) : test_partition의 48 행 "./floatstr.py"파일 self.failUnless (is_float_partition ( "20e2")) AssertionError -------------------------------------------------- -------------------- 33.670에서 8 번의 테스트 실행 실패 (실패 = 1)
코드는 다음과 같습니다 (Python 2.6, John Gietzen의 답변 에서 가져온 regexp ) :
def is_float_try(str):
try:
float(str)
return True
except ValueError:
return False
import re
_float_regexp = re.compile(r"^[-+]?(?:\b[0-9]+(?:\.[0-9]*)?|\.[0-9]+\b)(?:[eE][-+]?[0-9]+\b)?$")
def is_float_re(str):
return re.match(_float_regexp, str)
def is_float_partition(element):
partition=element.partition('.')
if (partition[0].isdigit() and partition[1]=='.' and partition[2].isdigit()) or (partition[0]=='' and partition[1]=='.' and pa\
rtition[2].isdigit()) or (partition[0].isdigit() and partition[1]=='.' and partition[2]==''):
return True
if __name__ == '__main__':
import unittest
import timeit
class ConvertTests(unittest.TestCase):
def test_re(self):
self.failUnless(is_float_re("20e2"))
def test_try(self):
self.failUnless(is_float_try("20e2"))
def test_re_perf(self):
print
print 're sad:', timeit.Timer('floatstr.is_float_re("12.2x")', "import floatstr").timeit()
print 're happy:', timeit.Timer('floatstr.is_float_re("12.2")', "import floatstr").timeit()
def test_try_perf(self):
print
print 'try sad:', timeit.Timer('floatstr.is_float_try("12.2x")', "import floatstr").timeit()
print 'try happy:', timeit.Timer('floatstr.is_float_try("12.2")', "import floatstr").timeit()
def test_partition_perf(self):
print
print 'partition sad:', timeit.Timer('floatstr.is_float_partition("12.2x")', "import floatstr").timeit()
print 'partition happy:', timeit.Timer('floatstr.is_float_partition("12.2")', "import floatstr").timeit()
def test_partition(self):
self.failUnless(is_float_partition("20e2"))
def test_partition2(self):
self.failUnless(is_float_partition(".2"))
def test_partition3(self):
self.failIf(is_float_partition("1234x.2"))
unittest.main()
답변
다양성을 위해 여기에 또 다른 방법이 있습니다.
>>> all([i.isnumeric() for i in '1.2'.split('.',1)])
True
>>> all([i.isnumeric() for i in '2'.split('.',1)])
True
>>> all([i.isnumeric() for i in '2.f'.split('.',1)])
False
편집 : 특히 지수가있을 때 플로트의 모든 경우를 견딜 수는 없습니다. 이를 해결하기 위해 다음과 같이 보입니다. 이것은 val은 int에 대한 float 및 False이지만 True 만 반환하지만 정규 표현식보다 성능이 떨어집니다.
>>> def isfloat(val):
... return all([ [any([i.isnumeric(), i in ['.','e']]) for i in val], len(val.split('.')) == 2] )
...
>>> isfloat('1')
False
>>> isfloat('1.2')
True
>>> isfloat('1.2e3')
True
>>> isfloat('12e3')
False
답변
이 정규식은 과학 부동 소수점 숫자를 확인합니다.
^[-+]?(?:\b[0-9]+(?:\.[0-9]*)?|\.[0-9]+\b)(?:[eE][-+]?[0-9]+\b)?$
그러나 최선의 방법은 파서를 시도해 보는 것입니다.