Функция «уменьшить» в Python не работает на «namedtuple»? - PullRequest
4 голосов
/ 04 октября 2011

У меня есть файл журнала, который отформатирован следующим образом:

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'

Похоже, что лямбда-функция работает непосредственно со свойством «actionDate », а не передает полный кортеж.Если я изменю лямбду на:

lambda x,y: min(x, y)

Это работает так, как я и ожидал.Есть идеи, почему это так?

1 Ответ

5 голосов
/ 04 октября 2011

Просто используйте:

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.

...