【问题标题】:map function to columns of list iterator将函数映射到列表迭代器的列
【发布时间】:2014-02-19 02:01:57
【问题描述】:

想象一下,我正在读取一个包含如下数字的 csv 文件:

1,6.2,10
5.4,5,11
17,1.5,5
...

而且真的很长。

我将使用这样的 csv 阅读器遍历这个文件:

import csv
reader = csv.reader('numbers.csv')

现在假设我有一些函数可以接受像 max 这样的迭代器:

max((float(rec[0]) for rec in reader))

这会找到第一列的最大值,不需要将整个文件读入内存。

但是,如果我想在 csv 文件的每一列上运行 max,但仍然没有将整个文件读入内存,该怎么办?

如果 max 被这样重写:

def max(iterator):
    themax = float('-inf')
    for i in iterator:
        themax = i if i > themax else themax
        yield
    yield themax

然后我可以做一些花哨的工作(并且必须)来实现这一点。

但是如果我限制问题并且不允许重写 max 呢?这可能吗?

谢谢!

【问题讨论】:

    标签: python csv iterator


    【解决方案1】:

    如果您对功能更强大的方法感到满意,您可以使用 functools.reduce 遍历文件,一次只将两行拉入内存,并累积列最大值。

    import csv
    from functools import reduce
    
    def column_max(row1, row2):
        # zip contiguous rows and apply max to each of the column pairs
        return [max(float(c1), float(c2)) for (c1, c2) in zip(row1, row2)]
    
    reader = csv.reader('numbers.csv')
    # calling `next` on reader advances its state by one row
    first_row = next(reader)
    column_maxes = reduce(column_max, reader, first_row)
    #
    #
    # another way to write this code is to unpack the reduction into explicit iteration
    column_maxes = next(reader) # advances `reader` to its second row
    for row in reader:
        column_maxes = [max(float(c1), float(c2)) for (c1, c2) in zip(column_maxes, row)]
    

    【讨论】:

      【解决方案2】:

      我将不再使用传递迭代器的函数,而是在阅读器上自行迭代:

      maxes = []
      for row in reader:
          for i in range(len(row)):
              if i > len(maxes):
                  maxes.append(row[i])
              else:
                  maxes[i] = max(maxes[i], row[i])
      

      最后,您将获得列表maxes,其中将包含每个最大值,而不会将整个文件放在内存中。

      【讨论】:

        【解决方案3】:
        def col_max(x0,x1):
            """x0 is a list of the accumulated maxes so far,
            x1 is a line from the file."""
            return [max(a,b) for a,b in zip(x0,x1)]
        

        现在 functools.reduce(col_max,reader,initializer) 将返回您想要的内容。您必须将初始化程序作为正确长度的 -inf 列表提供。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-09-27
          • 2021-03-23
          • 2012-04-27
          • 2015-02-11
          • 1970-01-01
          • 1970-01-01
          • 2021-09-30
          • 2020-07-24
          相关资源
          最近更新 更多