如何将字符串列表转换为混合数据类型

时间:2021-01-26 11:09:25

标签: python string

我有一个文件名列表,根据给定的正则表达式,我提取了一个 ID 元组。但是,这会产生字符串。实际 ID 是字符串和数字的组合,我想将其转换为正确的数据类型。处理这个问题的最佳方法是什么?

我考虑了两个选项:

使用 ast.literal_eval 进行评估

作为内置程序,它经过了良好的测试,而且比我可以合理生产的产品更通用。但是,它实际上可能过于笼统,可能会产生类似 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 的外观,因此这可能会有所不同。

1 个答案:

答案 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]