0

类似于“Python 中通过相同属性对对象列表进行分组和求和的最简洁方法是什么”,我有一个脚本,我需要在其中对对象列表的属性求和。但是,我的问题略有不同。

我有一类具有属性 V、W、X、Y 和 Z 的对象。我需要通过迭代和匹配属性 W、X 和 Y 与所有其他 W、X 和 Y 属性来求和属性 Z相同。生成由 W、X 和 Y 索引的新总和值。

这是对象的类:

class xb(object):
    def __init__(self, V, W, X, Y, Z):
       self.V = V
       self.W = W
       self.X = X
       self.Y = Y
       self.Z = Z

xbs = [xb()]

我最初的想法是通过一系列嵌套的 if 语句来做到这一点,但这会大大减慢处理速度,而且我确信我的逻辑完全不正常。

for xb in xbs:
    if xb.W == xb.W:
          if xb.X == xb.X:
              if xb.Y == xb.Y:
                  sum(xb.Z)

对此的任何建议将不胜感激!

4

2 回答 2

4

您可以使用 defaultdict 执行此操作:

from collections import defaultdict
indexed_sums = defaultdict(int)
for o in xbs:
    indexed_sums[(o.W, o.X, o.Y)] += o.Z

例如,如果您从(使用您的类定义xb)开始:

xbs = [xb(1, 2, 3, 4, 5),
       xb(1, 2, 3, 4, 5),
       xb(1, 2, 3, 4, 5),
       xb(1, 4, 3, 4, 5),
       xb(1, 4, 3, 4, 3),
       xb(1, 2, 3, 9, 3)]

你最终得到:

print dict(indexed_sums)
# {(4, 3, 4): 8, (2, 3, 4): 15, (2, 3, 9): 3}

因此,您可以得到 W、X、Y 的总和为 2、3、4:

indexed_sums[(2, 3, 4)]
# 15

请注意,defaultdict这里所做的工作很少(它只是一个默认从 0 开始的计数字典):主要是您正在索引(o.W, o.X, o.Y)字典中的元组。你可以做同样的事情没有defaultdict

indexed_sums = {}
for o in xbs:
    if (o.W, o.X, o.Y) not in indexed_sums:
        indexed_sums[(o.W, o.X, o.Y)] = 0
    indexed_sums[(o.W, o.X, o.Y)] += o.Z

defaultdict只是为您节省了两行。

于 2013-07-17T23:20:39.853 回答
0

这是一个非常肮脏的单线黑客:

{key:sum(g.Z for g in group)
    for key, group in 
    itertools.groupby(
        sorted(L, key=lambda p:tuple((operator.attrgetter(a)(p) for a in 'VWXYZ'))),
        key=lambda p:tuple(
                      (operator.attrgetter(a)(p) for a in 'VWXYZ')
                     )
    )
}

我根本不建议这样做(调试起来很痛苦),但我认为这是一个有趣的解决方案

于 2013-07-17T23:36:27.980 回答