计算特定属性

时间:2014-06-10 11:27:00

标签: python

说我有这样的事情:

from collections import namedtuple

Obj   = namedtuple('Obj', ['x', 'y']) 
items = [Obj(1,1), Obj(1,2), Obj(1,3), Obj(1,3), Obj(1,3)]

对于特定属性,count有没有办法?我希望你能做一些像:

test  = [ obj for obj in items if items.count(obj.y) > 1 ]

然而,这给出了一个空列表,而不是包含元素Obj(1,3)的列表。有没有人有一线解决方案?

4 个答案:

答案 0 :(得分:6)

分别创建计数映射;使用collections.Counter()使这很容易:

from collections import Counter

y_counts = Counter(obj.y for obj in items)
test = [obj for obj in items if y_counts[obj.y] > 1]

演示:

>>> from collections import Counter
>>> from collections import namedtuple
>>> Obj   = namedtuple('Obj', ['x', 'y']) 
>>> items = [Obj(1,1), Obj(1,2), Obj(1,3), Obj(1,3), Obj(1,3)]
>>> y_counts = Counter(obj.y for obj in items)
>>> [obj for obj in items if y_counts[obj.y] > 1]
[Obj(x=1, y=3), Obj(x=1, y=3), Obj(x=1, y=3)]

答案 1 :(得分:1)

要从obj中获取items所有对象obj.y,其中test = [obj for obj in items if sum(1 for o in items if o.y == obj.y) > 1] 在列表中出现多次,在一行中:

[Obj(x=1, y=3), Obj(x=1, y=3), Obj(x=1, y=3)]

这给了我:

O(n**2)

但请注意,此“算法”为collections.defaultdict(list),效率不高。相反,创建一个字典(您可以使用d = {} for obj in items: if obj.y not in d: d[obj.y] = [] d[obj.y].append(obj) )简化:

test = []
for v in d.values():
    if len(v) > 1:
        test.extend(v)

然后获取长于1的值:

{{1}}

答案 2 :(得分:0)

如果我理解你要做的事情,那就收集具有相同y值的对象数量的项目

一种简单的方法是,

from collections import Counter

counter = Counter(items)

然后,你需要的测试,

test = [obj for obj, count in counter.items() if count > 1]

答案 3 :(得分:0)

仅供记录,因为Martijn Pieters answer显然更好更容易。问题在于count依赖于__eq__函数,因此您可以覆盖它以实现结果。

from collections import namedtuple 

class CustomTuple(namedtuple('Obj', ['x', 'y'])):
    def __eq__(self, other):
        return self.y == other.y

然后你可以使用:

items = [CustomTuple(1,1), CustomTuple(1,2), CustomTuple(1,3), CustomTuple(1,3), CustomTuple(1,3)]
print [obj for obj in items if items.count(obj) > 1]

或直接:

[obj for obj, count in Counter(items).iteritems() if count > 1]

基本上,您只是说CustomTuple('value', y)总是等于CustomTuple('another_value', y).所有y