【问题标题】:python find duplicate objects in a listpython在列表中查找重复的对象
【发布时间】:2020-03-13 10:15:40
【问题描述】:

我有一个清单

l = [object0, object1, object2, object3, object4....object499]

最大长度永远不会超过 500

所有对象都有属性x、y、z、a

如果在 object.x 中重复,我必须修改 object.y:

if object9.x == object10.x:
  object9.y = object9.z * object9.a/1000
  object10.y = object10.y - object9.z * object9.a/1000

保证重复将在连续的对象中。

可能有两个以上的重复,例如

object12.x == object13.x == object14.x

因此修改将根据修改后的第二个副本的值以与第三个副本相同的方式进行。

我已经编写了一个循环来执行此操作,但正在考虑是否有任何 pythonic/更快的方式来执行此操作。 我正在使用python3.7

编辑:

tag = None
for i, o in enumerate(l):
  if tag is None:
     x_a = o.x
  elif x_a == o.x #duplicate found
    temp = o.y
    c_over = 0
    c_value = o[i-1].z * o[i-1].a/1000
    if c_value < o[i-1].y:
       o[i-1].y = c_value
       c_over = temp - c_value #carry over value
    o[i] = c_over # either zero of carry over value
  x_a = o.x 

【问题讨论】:

  • 您能否展示您现有的循环,以便其他人可以建议如何改进它,或者建议其他方法?
  • 你想要itertools.groupby,将operator.attrgetter('x')作为key函数。
  • 您可以使用 for (prev, current) in zip(l, l[1:]): 迭代列表中的情侣
  • 现在枚举列表,如果发现重复,则修改前一个元素。贴出循环的代码

标签: python python-3.x python-3.7


【解决方案1】:

由于您正在修改对象的属性,因此您可以通过zip 循环连续对:

for a, b in zip(l, l[1:]):
    if a.x == b.x:
        a.y = a.z * a.a/1000
        b.y = b.y - a.y

【讨论】:

  • 比这更棘手的是,可能有一个c,其中b.x == c.x,但由于您在检查c之前修改了b,所以您错过了它。
  • @Ev.Kounis b.x 从未被修改过,因此这里没有遗漏任何内容。 x 用于检查,y 被修改。
  • 你是对的。这个问题有点模棱两可,想起来更难一点。我不清楚修改是从组的开头还是结尾发生。假设 (a, b, c) 的三元组,c 的修改将在您和我的答案中使用已修改的 b 值进行。
  • @Ev.Kounis 这是 OP 明确要求的:"[...] 因此修改将根据修改后的第二个副本的值以与第三个副本相同的方式进行。"
【解决方案2】:

@Shadow Ranger's comment 绝对是这里的必经之路。我没有对此进行任何测试,但它应该可以解决问题

import itertools
import operator


l = [object0, object1, object2, object3, object4]

for k, g in itertools.groupby(l, key=operator.attrgetter('x')):
    l = list(g)
    for o1, o2, in zip(l, l[1:]):  # Note 1, 2
        o1.y = o1.z * o1.a / 1000
        o2.y = o2.z - o1.y

注意事项:

  1. 假设您从头到尾修改组。如果你想反过来做,你必须用zip(l[len(l)-2::-1], l[::-1])替换zip(l, l[1:])
  2. 感谢@ShadowRanger 指出不需要if 检查(由zip 处理)

【讨论】:

  • 注意:您不需要检查长度(如果l[1:] 为空,zip 将立即终止),如果您正在向前运行,您可以使用itertools.tee , 完全避免 listifying (这使得它完全懒惰;在你需要它们之前没有实现元素)。 g, g2 = itertools.tee(g), next(g2), for o1, o2 in zip(g, g2):
猜你喜欢
  • 2021-08-26
  • 1970-01-01
  • 1970-01-01
  • 2011-07-04
  • 1970-01-01
  • 2011-07-27
  • 2014-12-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多