Идея в том, чтобы использовать сокращение, чтобы избежать повторных итераций. Кроме того, это не создает никаких дополнительных структур данных, если память является проблемой для вас. Вы начинаете со словаря со своими счетчиками ({'div2': 0, 'div3': 0}
) и увеличиваете их на протяжении итерации.
def increment_stats(stats, n):
if n % 2 == 0: stats['div2'] += 1
if n % 3 == 0: stats['div3'] += 1
return stats
r = xrange(1, 10)
stats = reduce(increment_stats, r, {'div2': 0, 'div3': 0})
print stats
Если вы хотите посчитать что-нибудь более сложное, чем делители, было бы целесообразно использовать более объектно-ориентированный подход (с теми же преимуществами), инкапсулируя логику для извлечения статистики.
class Stats:
def __init__(self, div2=0, div3=0):
self.div2 = div2
self.div3 = div3
def increment(self, n):
if n % 2 == 0: self.div2 += 1
if n % 3 == 0: self.div3 += 1
return self
def __repr__(self):
return 'Stats(%d, %d)' % (self.div2, self.div3)
r = xrange(1, 10)
stats = reduce(lambda stats, n: stats.increment(n), r, Stats())
print stats
Пожалуйста, укажите на любые ошибки.
@ Хенрик: Я думаю, что первый подход менее удобен в обслуживании, так как вам нужно контролировать инициализацию словаря в одном месте и обновлять в другом, а также использовать строки для ссылки на каждый стат (вместо того, чтобы иметь атрибуты). И я не думаю, что в этом случае ОО является излишним, поскольку вы сказали, что предикаты и объекты будут сложными в вашем приложении. На самом деле, если бы предикаты были действительно простыми, я бы даже не стал использовать словарь, с одним списком фиксированного размера было бы просто замечательно. Ура:)