“确定”;“价值类型”;来自python中的字符串
我试图用python编写一个函数,它将确定字符串中的值的类型;比如说 如果in字符串为1或0或True或False,则值为位 如果in字符串为0-9*,则值为INT 如果字符串中的值为0-9+。0-9+则该值为浮点值 如果在字符串中为stg,则更多(文本等)值为文本 到目前为止,我有stg喜欢“确定”;“价值类型”;来自python中的字符串,python,regex,types,Python,Regex,Types,我试图用python编写一个函数,它将确定字符串中的值的类型;比如说 如果in字符串为1或0或True或False,则值为位 如果in字符串为0-9*,则值为INT 如果字符串中的值为0-9+。0-9+则该值为浮点值 如果在字符串中为stg,则更多(文本等)值为文本 到目前为止,我有stg喜欢 def dataType(string): odp='' patternBIT=re.compile('[01]') patternINT=re.compile('[0-9]+') patter
def dataType(string):
odp=''
patternBIT=re.compile('[01]')
patternINT=re.compile('[0-9]+')
patternFLOAT=re.compile('[0-9]+\.[0-9]+')
patternTEXT=re.compile('[a-zA-Z0-9]+')
if patternTEXT.match(string):
odp= "text"
if patternFLOAT.match(string):
odp= "FLOAT"
if patternINT.match(string):
odp= "INT"
if patternBIT.match(string):
odp= "BIT"
return odp
但是我不太擅长在python中使用正则表达式。你能告诉我,我做错了什么吗?例如,它对2010-00-10不起作用,2010-00-10应该是文本,但是是INT或20.90,应该是float,但是是INT,在你走太远的正则表达式之前,你考虑过使用 示例:
In [35]: ast.literal_eval('1')
Out[35]: 1
In [36]: type(ast.literal_eval('1'))
Out[36]: int
In [38]: type(ast.literal_eval('1.0'))
Out[38]: float
In [40]: type(ast.literal_eval('[1,2,3]'))
Out[40]: list
不妨使用Python为您解析它
好的,这里有一个更大的例子:
import ast, re
def dataType(str):
str=str.strip()
if len(str) == 0: return 'BLANK'
try:
t=ast.literal_eval(str)
except ValueError:
return 'TEXT'
except SyntaxError:
return 'TEXT'
else:
if type(t) in [int, long, float, bool]:
if t in set((True,False)):
return 'BIT'
if type(t) is int or type(t) is long:
return 'INT'
if type(t) is float:
return 'FLOAT'
else:
return 'TEXT'
testSet=[' 1 ', ' 0 ', 'True', 'False', #should all be BIT
'12', '34l', '-3','03', #should all be INT
'1.2', '-20.4', '1e66', '35.','- .2','-.2e6', #should all be FLOAT
'10-1', 'def', '10,2', '[1,2]','35.9.6','35..','.']
for t in testSet:
print "{:10}:{}".format(t,dataType(t))
输出:
1 :BIT
0 :BIT
True :BIT
False :BIT
12 :INT
34l :INT
-3 :INT
03 :INT
1.2 :FLOAT
-20.4 :FLOAT
1e66 :FLOAT
35. :FLOAT
- .2 :FLOAT
-.2e6 :FLOAT
10-1 :TEXT
def :TEXT
10,2 :TEXT
[1,2] :TEXT
35.9.6 :TEXT
35.. :TEXT
. :TEXT
如果你确实必须有一个正则表达式解决方案,它会产生相同的结果,这里是:
def regDataType(str):
str=str.strip()
if len(str) == 0: return 'BLANK'
if re.match(r'True$|^False$|^0$|^1$', str):
return 'BIT'
if re.match(r'([-+]\s*)?\d+[lL]?$', str):
return 'INT'
if re.match(r'([-+]\s*)?[1-9][0-9]*\.?[0-9]*([Ee][+-]?[0-9]+)?$', str):
return 'FLOAT'
if re.match(r'([-+]\s*)?[0-9]*\.?[0-9][0-9]*([Ee][+-]?[0-9]+)?$', str):
return 'FLOAT'
return 'TEXT'
然而,我不能推荐正则表达式而不是ast版本;让Python来解释它认为这些数据类型是什么,而不是用正则表达式来解释它们…您也可以使用json
import json
converted_val = json.loads('32.45')
type(converted_val)
输出
type <'float'>
它匹配,因此odp
设置为“text”
然后,您的脚本执行以下操作:
if patternFLOAT.match(str_obj):
不匹配,odp
仍然等于“text”
部分匹配odp
设置为“INT”
由于match返回部分匹配,因此将计算多个if
语句,最后一个计算语句将确定在odp
中返回哪个字符串
您可以执行以下几项操作之一:
if
语句,请使用if
和elif
,以便只计算要匹配的第一条语句...
match = patternINT.match(str_obj)
if match:
if match.end() == match.endpos:
#do stuff
...
你说你用这些作为输入:
- 2010-00-10(是整数,不是文本)
- 20.90(为整数,非浮动)
def dataType(string):
odp=''
patternBIT=re.compile('[01]')
patternINT=re.compile('[0-9]+')
patternFLOAT=re.compile('[0-9]+\.[0-9]+')
patternTEXT=re.compile('[a-zA-Z0-9]+')
if patternTEXT.match(string):
odp= "text"
if patternFLOAT.match(string):
odp= "FLOAT"
if patternINT.match(string):
odp= "INT"
if patternBIT.match(string):
odp= "BIT"
return odp
问题
您的if
语句将按顺序执行-即:
if patternTEXT.match(string):
odp= "text"
if patternFLOAT.match(string):
odp= "FLOAT"
if patternINT.match(string)
odp= "INT"
if patternBIT.match(string):
odp= "BIT"
“2010-00-10”匹配您的文本模式,但随后它将尝试匹配您的浮点模式(失败,因为没有
),然后匹配int
模式,该模式有效,因为它确实包含[0-9]+
你应使用:
if patternTEXT.match(string):
odp = "text"
elif patternFLOAT.match(string):
...
虽然对于您的情况,您可能希望从更具体到不太具体,因为正如您所看到的,文本内容也可能是int(反之亦然)。您还需要改进正则表达式,因为“文本”模式只匹配字母数字输入,而不匹配特殊符号
虽然我更喜欢AST解决方案,但我会提出自己的建议:
def get_type(string):
if len(string) == 1 and string in ['0', '1']:
return "BIT"
# int has to come before float, because integers can be
# floats.
try:
long(string)
return "INT"
except ValueError, ve:
pass
try:
float(string)
return "FLOAT"
except ValueError, ve:
pass
return "TEXT"
运行示例:
In [27]: get_type("034")
Out[27]: 'INT'
In [28]: get_type("3-4")
Out[28]: 'TEXT'
In [29]: get_type("20.90")
Out[29]: 'FLOAT'
In [30]: get_type("u09pweur909ru20")
Out[30]: 'TEXT'
答复
例如,它不适用于2010-00-10,应该是文本,但是
是INT或20.90,应该是float,但是是INT
>>重新导入
>>>patternINT=re.compile('[0-9]+'))
>>>打印Patternit.match('2010-00-10')
>>>patternINT=re.compile(“[0-9]+$”)
>>>打印模式匹配('2010-00-10')
没有一个
>>>打印patternit.match('2010')
不要忘记
$
来限制字符串的结尾。您的输入是什么样子的?请记住,match
仅在字符串开头匹配。您的代码什么时候不起作用?请发布您试图解析的文件的示例,以便我们可以复制错误并按预期检查解决方案的工作情况。您不需要使用正则表达式-您可以尝试使用int将字符串转换/强制转换为其他类型()
,float()
。对于位,您可以检查字符串长度是否为1,并且在(0,1)中是否为。然后用try except
包装转换。但这与正则表达式无关。我已更新了原始的postBut类型(json.loads('1'))
返回int
而OP想要bool
@San4ez:you're对,这是一个特殊情况。就像“bit”一样,@JoelCornettjson
模块在那里并不明显+1@San4ez:谢谢:)另外,我意识到我的答案实际上并没有回答OP的问题“我做错了什么?”。编辑以包含该值。感谢您的回答,但我不知道如何使用ast来确定“位”和“文本”值(特别是对于文本-它给了我一个错误,当我调用ast.literal('string')@Johnzzz时,请尝试ast.literal('string'))
。最外面的引号创建一个字符串,但它不会被ast.literal
解析为字符串,除非它周围还有引号。@johnzz,然后测试“位”很容易;只需检查值是否在集合中((真,假))
。(0
和1
通过了这个测试,至少在Python 2.6中通过了True
和False
,在新版本中可能会有所不同。)@carrot top,非常感谢。我并不明确地想使用正则表达式,但这似乎是一个很好的示例,我可以在其中学习正则表达式:)因此,非常感谢您对re.match
的回答。您不需要初始的^
锚定。此方法已从字符串开始搜索。无论如何,您都需要带有re.search
Read+1的锚定。
def get_type(string):
if len(string) == 1 and string in ['0', '1']:
return "BIT"
# int has to come before float, because integers can be
# floats.
try:
long(string)
return "INT"
except ValueError, ve:
pass
try:
float(string)
return "FLOAT"
except ValueError, ve:
pass
return "TEXT"
In [27]: get_type("034")
Out[27]: 'INT'
In [28]: get_type("3-4")
Out[28]: 'TEXT'
In [29]: get_type("20.90")
Out[29]: 'FLOAT'
In [30]: get_type("u09pweur909ru20")
Out[30]: 'TEXT'
>>> import re
>>> patternINT=re.compile('[0-9]+')
>>> print patternINT.match('2010-00-10')
<_sre.SRE_Match object at 0x7fa17bc69850>
>>> patternINT=re.compile('[0-9]+$')
>>> print patternINT.match('2010-00-10')
None
>>> print patternINT.match('2010')
<_sre.SRE_Match object at 0x7fa17bc69850>