Python 将函数列表应用于包含 None 值的项目列表

Python applying a list of functions to a list of items including None values

如果我有一个要转换类型的数据项列表

例如:

row = (u'2013-13-04 00:00:00',
     u'P1',
     u'BRT64510',
     u'CHUCKLES MOTOR COMPANY',
     u'123',
     None,
     u'2345',
     u'100000',
     u'150000000',
     None,
     u'100000',
     None,
     u'123345',
     u'1234567',
     u'122445',
     None)

和转换公式列表,例如:

import datetime
dt = datetime.datetime
st = lambda x: dt.strptime(x,'%Y-%m-%d %H:%M:%S')
f = lambda x: float(x)
s = lambda x: str(x)

conversion = [st, s, s, s, f, f, f, f, f, f, f, f, f, f, f, f]

我正在尝试应用以下内容:

result =[func(value) for func,value in zip(conversion,row)]

当然我在 NULL : None 值方面遇到了错误。

是否有快速修复程序可以让我将函数列表应用于项目列表,同时将空值保留为空值?此清理将应用于大量记录,因此我不知道哪些值会提前为空。

谢谢

result = [func(value) if value is not None else None
          for func, value in zip(conversion, row)]

只需更改您的 f 函数,像这样

f = lambda x: float(x) if isinstance(x, unicode) else x

或者这个

f = lambda x: float(x) if x is not None else x

现在,如果输入的类型是 unicode(或者在第二种情况下,如果 x 不是 None),它将调用 float

在你的情况下,你可以简单地避免 lambda 函数,并使

conversion = [st, str, str, str, float, ...]

然后将条件包含在列表理解本身中,像这样

[val if value is None else func(val) for func, val in zip(conversion, row)]

注意:您的日期格式不正确,您可能需要更改格式,像这样

dt.strptime(x,'%Y-%d-%m %H:%M:%S')

以便匹配

'2013-13-04 00:00:00'

另一种选择是为 NULL 个值添加 identity 函数。

>>> i = lambda x: x
>>> conversion = [st, s, s, s, f, i, f, f, f, i, f, i, f, f, f, i]
>>> result = [func(value) for func, value in zip(conversion, row)]

顺便说一句,您的日期时间转换格式不正确。应该是这样的:

st = lambda x: dt.strptime(x,'%Y-%d-%m %H:%M:%S') 

这个功能也可以考虑itertools.starmap()

让我们假设您创建一个函数,该函数接受一个函数和一个参数以及 returns 函数的值 returns,

def myApply(f, v): 
    try: return f(v)
    except: return None

然后,您可以使用 starmap 按顺序将这些函数应用于值:

import itertools as itt
result = itt.starmap( myApply, zip( conversion, row ) )

try-except方法将能够捕获各种问题。但是,它会默默地只是将结果转换为None。如果您不想要这种行为,您可以考虑将 except 选项更改为更有意义的内容 ...

result =[None if isinstance(value, type(None)) else func(value) for func,value in zip(conversion,row)]

使用带有转换函数的try/except结构:

def conv(f, x):
    try:
        return f(x)
        # TypeError catches float(None)
        # add ValueError if you might get float('abc') for example...
    except TypeError: 
        return x

result =[conv(func, value) for func,value in zip(conversion,row)]   

然后你的方法就完美了(一旦你更正了dt.strstrptime(x,'%Y-%d-%m %H:%M:%S')):

import datetime
dt = datetime.datetime
st = lambda x: dt.strptime(x,'%Y-%d-%m %H:%M:%S')
f = lambda x: float(x)
s = lambda x: str(x)

conversion = [st, s, s, s, f, f, f, f, f, f, f, f, f, f, f, f]    

def conv(f, x):
    try:
        return f(x)
    except (TypeError, ValueError):
        return x

result =[conv(func, value) for func,value in zip(conversion,row)]    
print result    

打印:

[datetime.datetime(2013, 4, 13, 0, 0), 'P1', 'BRT64510', 'CHUCKLES MOTOR COMPANY', 123.0, None, 2345.0, 100000.0, 150000000.0, None, 100000.0, None, 123345.0, 1234567.0, 122445.0, None]