与特定属性有关的计数

2024-09-30 16:25:48 发布

您现在位置: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)的列表。有人有单线解决方案吗?你知道吗


Tags: infromtestimportobj列表forif
3条回答

分别创建计数的映射;使用^{}可以很容易地实现这一点:

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)]

要从列表中多次出现itemsobj获取所有对象,请在一行中执行以下操作:

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)

如果我知道你想做什么,那就是收集具有相同y值的对象数的项

一个简单的方法是

from collections import Counter

counter = Counter(items)

然后,你需要的测试

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

相关问题 更多 >