Python中"reduce"函数在"namedtuple"上不工作?

5 投票
1 回答
601 浏览
提问于 2025-04-17 03:39

我有一个日志文件,格式如下:

datetimestring \t username \t transactionName \r\n

我想对这个数据集进行一些统计分析。我写了以下代码:

import time
import collections
file = open('Log.txt', 'r')

TransactionData = collections.namedtuple('TransactionData', ['transactionDate', 'user', 'transactionName'])
transactions = list()

for line in file:
    fields = line.split('\t')

    transactionDate = time.strptime(fields[0], '%Y-%m-%d %H:%M:%S')
    user = fields[1]
    transactionName = fields[2]

    transdata = TransactionData(transactionDate, user, transactionName)
    transactions.append(transdata)

file.close()

minDate = reduce(lambda x,y: min(x.transactionDate, y.transactionDate), transactions)
print minDate

因为这个数据集很简单,我不想为它定义一个类,所以我用了命名元组。当我尝试运行时,出现了这个错误:

Traceback (most recent call last):
  File "inquiriesStat.py", line 20, in <module>
    minDate = reduce(lambda x,y: min(x.transactionDate, y.transactionDate), transactions)
  File "inquiriesStat.py", line 20, in <lambda>
    minDate = reduce(lambda x,y: min(x.transactionDate, y.transactionDate), transactions)
AttributeError: 'time.struct_time' object has no attribute 'transactionDate'

看起来这个 lambda 函数直接在 'transactionDate' 属性上操作,而不是传入整个元组。如果我把 lambda 改成:

lambda x,y: min(x, y)

它就能按我预期的那样工作了。你知道为什么会这样吗?

1 个回答

6

简单使用:

minDate = min(t.transactionDate for t in transactions)

下面来解释一下为什么你的代码不工作。

假设 transactions = [t1, t2, t3],其中 t1...t3 是三个命名元组。

根据 reduce 的定义,你的代码:

reduce(lambda x,y: min(x.transactionDate, y.transactionDate), transactions)

相当于

min(min(t1.transactionDate, t2.transactionDate).transactionDate, t3.transactionDate)

很明显,里面的 min() 返回的是 time.struct_time,而不是命名元组,所以当 reduce 尝试对它使用 .transactionDate 时,就会出错。

有办法可以解决这个问题,并且可以用 reduce 来处理这个问题。不过,直接使用 min 就能解决,而且我觉得这样比用 reduce 清晰多了。

撰写回答