我有一个文件名列表,根据给定的正则表达式,我提取了一个 ID 元组。但是,这会产生字符串。实际 ID 是字符串和数字的组合,我想将其转换为正确的数据类型。处理这个问题的最佳方法是什么?
我考虑了两个选项:
作为内置程序,它经过了良好的测试,而且比我可以合理生产的产品更通用。但是,它实际上可能过于笼统,可能会产生类似 None
或 bool 的内容。这不是我当前数据的问题,但需要考虑以备将来证明。
编辑:使用literal_eval不起作用,因为像'02'这样的东西不是有效的Python表达式。
目前正则表达式保存为字符串。该文件还可以包含应如何解释每个捕获组的规范。
一个非常基本的版本是只列出数据类型(字符串、整数、浮点数),然后像这样遍历它们:
for i, spec in enumerate(specifications):
if spec == 'int':
ID[i] = int(ID[i])
elif spec == 'float':
ID[i] = float(ID[i])
elif spec == 'string':
pass
else:
raise ValueError(f'Incorrect Specification {spec} at index {i}')
但这似乎会在处理额外规范时引发人为错误,并引入额外的复杂性。
我在这方面没有任何经验,所以我不知道陷阱是什么。这里最好的方法是什么?
编辑:
文件名可能类似于 "FOR_Set2_CREE_1.79_0010APC.aver.dat"
它通过正则表达式转换为字符串列表 ["FOR", "2", "CREE", "1.79", "10"]
。
然后需要将其强制转换为 ["FOR", 2, "CREE", 1.79, 10]
。
我无法控制 ID 的外观,因此这可能会有所不同。
答案 0 :(得分:0)
以下函数将完成这项工作(适用于您提供的示例),但不保证高效或最小:
(当前时间:42.8 µs ± 4.69 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
)
import re
def func(s):
# Split on '_'
l = s.split('_')
# Split on '.'
l = [x.split('.') if not x.replace('.','',1).isdigit() else float(x) for x in l]
# Unroll any nested list
l = [x[0] if type(x)==list and len(x)==1 else x for x in l]
l2 = list()
for i in l:
if type(i)==list:
for j in i:
l2.append(j)
else:
l2.append(i)
l = l2
print('Final shortlist for matching: {}'.format(l))
# Perform regex based filtering
l2 = list()
for x in l:
if type(x)==str:
pat1 = r'([A-Z]*)([a-z]*)(\d+)'
pat2 = r'[A-Z]+'
m1 = re.match(pat1, x)
m2 = re.match(pat2, x)
if m1 is not None:
l2.append(int(m1.group(3)))
elif m2 is not None:
l2.append(m2.group(0))
else:
l2.append(x)
print('Required terms: {}'.format(l2))
s = 'FOR_Set2_CREE_1.79_0010APC.aver.dat'
func(s)
以上代码的输出:
Final shortlist for matching: ['FOR', 'Set2', 'CREE', 1.79, '0010APC', 'aver', 'dat']
Required terms: ['FOR', 2, 'CREE', 1.79, 10]