使用地图应用多个功能

时间:2016-03-08 04:04:01

标签: python functional-programming

我有2D数据,我想要应用多个功能。实际代码使用xlrd.xlsx文件,但我会提供以下样板,以便输出易于重现。

class Data:
    def __init__(self, value):
        self.value = value

class Sheet:
    def __init__(self, data):
        self.data = [[Data(value) for value in row.split(',')] for row in data.split('\n')]
        self.ncols = max(len(row) for row in self.data)

    def col(self, index):
        return [row[index] for row in self.data]

创建工作表:

fake_data = '''a, b, c,
               1, 2, 3, 4
               e, f, g, 
               5, 6, i, 
                , 6,  , 
                ,  ,  ,  '''

sheet = Sheet(fake_data)

在此对象中,data包含一个二维字符串数组(按照输入格式),我想对该对象的列执行操作。到目前为止,我无法控制任何事情。

我想对此结构做三件事:将行转换为列,从每个value对象中提取Data,然后尝试将值转换为float。如果该值不是float,则应将其转换为带有剥离空白的str

from operators import attrgetter

# helper function
def parse_value(value):
    try:
        return float(value)
    except ValueError:
        return str(value).strip()

# transpose
raw_cols = map(sheet.col, range(sheet.ncols))

# extract values
value_cols = (map(attrgetter('value'), col) for col in raw_cols)

# convert values
typed_cols = (map(parse_value, col) for col in value_cols)

# ['a', 1.0, 'e', 5.0, '',  '']
# ['b', 2.0, 'f', 6.0, 6.0, '']
# ['c', 3.0, 'g', 'i', '',  '']
# ['',  4.0, '',  '',  '',  '']

可以看出map两次应用于每列。在其他情况下,我想将一个函数应用于每列两次以上。

是否有更好的方法将多个函数映射到iterable的条目?更重要的是,有没有避免生成器理解并直接将映射应用于每个内部可迭代?或者,有没有更好和可扩展的方法来解决这个问题?

请注意,此问题并非特定于xlrd,它只是当前的用例。

2 个答案:

答案 0 :(得分:6)

似乎最简单的解决方案是滚动自己的函数,将多个函数应用于同一个迭代函数。

def map_many(iterable, function, *other):
    if other:
        return map_many(map(function, iterable), *other)
    return map(function, iterable)

这里的缺点是用法与map(function, iterable)相反,将map扩展为接受参数(如Python 3.X中的那样)会很尴尬。

用法:

map_many([0, 1, 2, 3, 4], str, lambda s: s + '0', int)
# [0, 10, 20, 30, 40]

答案 1 :(得分:4)

您可以使用map

轻松加入最后两个lambda来电
typed_cols = (map(lambda element:parse_value(element['value']), col)
              for col in value_cols)

虽然你可以在Sheet.col内解析和提取内容,但会影响代码的可读性。