У меня есть код 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 и посмотреть, удастся ли оно, как описано в этом вопросе .
У кого-нибудь есть другие идеи? Мнения об относительных достоинствах раздела и подходов "попробуй / поймай"?
python
string
type-conversion
Крис Апчерч
источник
источник
Ответы:
Я бы просто использовал ..
try: float(element) except ValueError: print "Not a float"
..это просто, и это работает
Другой вариант - регулярное выражение:
import re if re.match(r'^-?\d+(?:\.\d+)?$', element) is None: print "Not 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
источник
isfloat(" 1.23 ")
иisfloat(" \n \t 1.23 \n\t\n")
. Полезно в веб-запросах; не нужно сначала обрезать пробелы.isfloat("1_2_3.4")
->True
'1.43'.replace('.','',1).isdigit()
который вернется,
true
только если он есть или нет '.' в строке цифр.'1.4.3'.replace('.','',1).isdigit()
вернется
false
'1.ww'.replace('.','',1).isdigit()
вернется
false
источник
[i for i in df[i].apply(lambda x: str(x).replace('.','').isdigit()).any()]
TL; DR :
try: except:
метод - лучший собственный метод Python.Есть еще один метод, доступный через сторонний модуль под названием fastnumbers (раскрытие, я являюсь автором); он предоставляет функцию isfloat . Я взял пример unittest, описанный Джейкобом Габриэльсоном в этом ответе , но добавил
fastnumbers.isfloat
метод. Я также должен отметить, что в примере Джейкоба не было должного внимания к параметру регулярного выражения, потому что большая часть времени в этом примере была потрачена на глобальный поиск из-за оператора точки ... Я изменил эту функцию, чтобы дать более справедливое сравнение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
метод вполне подойдет.источник
Если вы заботитесь о производительности (а я не предлагаю вам это делать), подход на основе попыток является явным победителем (по сравнению с подходом на основе разделов или подходом регулярного выражения), если вы не ожидаете много недопустимые строки, и в этом случае он потенциально медленнее (предположительно из-за стоимости обработки исключений).
Опять же, я не предлагаю вам заботиться о производительности, я просто предоставляю вам данные, если вы делаете это 10 миллиардов раз в секунду или что-то в этом роде. Кроме того, код на основе разделов не обрабатывает хотя бы одну допустимую строку.
Вот код (Python 2.6, регулярное выражение взято из ответа Джона Гитцена ):
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
Изменить: я уверен, что он не будет поддерживать все случаи с плавающей запятой, хотя особенно когда есть показатель степени. Чтобы решить эту проблему, это выглядит так. Это вернет True, только val является float и False для int, но, вероятно, менее производительно, чем регулярное выражение.
>>> 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)?$
Однако я считаю, что лучше всего попробовать воспользоваться парсером.
источник
Если вам не нужно беспокоиться о научных или других выражениях чисел и вы работаете только со строками, которые могут быть числами с точкой или без нее:
Функция
def is_float(s): result = False if s.count(".") == 1: if s.replace(".", "").isdigit(): result = True return result
Лямбда-версия
is_float = lambda x: x.replace('.','',1).isdigit() and "." in x
пример
if is_float(some_string): some_string = float(some_string) elif some_string.isdigit(): some_string = int(some_string) else: print "Does not convert to int or float."
Таким образом, вы случайно не преобразуете то, что должно быть int, в float.
источник
Упрощенная версия функции
is_digit(str)
, которой хватает в большинстве случаев (без учета экспоненциальной записи и значения "NaN" ):def is_digit(str): return str.lstrip('-').replace('.', '').isdigit()
источник
Я использовал уже упомянутую функцию, но вскоре заметил, что такие строки, как «Nan», «Inf» и их вариации, считаются числами. Итак, я предлагаю вам улучшенную версию функции, которая будет возвращать false для этого типа ввода и не откажет вариантам "1e3":
def is_float(text): # check for nan/infinity etc. if text.isalpha(): return False try: float(text) return True except ValueError: return False
источник
if text.isalpha():
чека?Попробуйте преобразовать в float. Если есть ошибка, выведите исключение ValueError.
try: x = float('1.23') print('val=',x) y = float('abc') print('val=',y) except ValueError as err: print('floatErr;',err)
Выход:
val= 1.23 floatErr: could not convert string to float: 'abc'
источник
Передав словарь в качестве аргумента, он преобразует строки, которые можно преобразовать в float, и оставит другие
def covertDict_float(data): for i in data: if data[i].split(".")[0].isdigit(): try: data[i] = float(data[i]) except: continue return data
источник
Я искал похожий код, но похоже, что использование try / excepts - лучший способ. Вот код, который я использую. Он включает функцию повтора, если ввод недопустим. Мне нужно было проверить, было ли введенное значение больше 0, и если да, преобразовать его в число с плавающей запятой.
def cleanInput(question,retry=False): inputValue = input("\n\nOnly positive numbers can be entered, please re-enter the value.\n\n{}".format(question)) if retry else input(question) try: if float(inputValue) <= 0 : raise ValueError() else : return(float(inputValue)) except ValueError : return(cleanInput(question,retry=True)) willbefloat = cleanInput("Give me the number: ")
источник
def try_parse_float(item): result = None try: float(item) except: pass else: result = float(item) return result
источник
Я попробовал некоторые из вышеперечисленных простых вариантов, используя пробный тест для преобразования в число с плавающей запятой, и обнаружил, что в большинстве ответов есть проблема.
Простой тест (в соответствии с приведенными выше ответами):
entry = ttk.Entry(self, validate='key') entry['validatecommand'] = (entry.register(_test_num), '%P') def _test_num(P): try: float(P) return True except ValueError: return False
Проблема возникает, когда:
Затем вы пытаетесь,
float('-')
что не удаетсяЗатем вы пытаетесь,
float('')
что тоже не удаетсяУ меня было быстрое решение:
def _test_num(P): if P == '' or P == '-': return True try: float(P) return True except ValueError: return False
источник
вроде бы просто.
Обрабатывает значения, хранящиеся в виде строки, int или float
источник