使用地图应用多个功能

Jar*_*uen 8 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]
Run Code Online (Sandbox Code Playgroud)

创建工作表:

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

sheet = Sheet(fake_data)
Run Code Online (Sandbox Code Playgroud)

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

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

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, '',  '',  '',  '']
Run Code Online (Sandbox Code Playgroud)

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

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

请注意,这个问题并不是特定的xlrd,它只是当前的用例.

Jar*_*uen 8

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

def map_many(iterable, function, *other):
    if other:
        return map_many(map(function, iterable), *other)
    return map(function, iterable)
Run Code Online (Sandbox Code Playgroud)

这里的缺点是使用是相反的,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]
Run Code Online (Sandbox Code Playgroud)


Anu*_*hne 5

您可以map使用lambda,

typed_cols = (map(lambda element:parse_value(element['value']), col)
              for col in value_cols)
Run Code Online (Sandbox Code Playgroud)

虽然您可以在内部进行类似的解析和提取Sheet.col,但 IMO 会影响代码的可读性。