【问题标题】:How to ignore duplicate object values from display如何从显示中忽略重复的对象值
【发布时间】:2020-09-08 01:24:06
【问题描述】:

我有一个具有 3 个属性 a、b 和 c 的测试类。 已经创建了 3 个类的实例,并为属性设置了适当的值, 鉴于“a”属性始终是唯一的,并且当两个具有相同“b”值的对象将始终具有相同的“c”值时。 如果看到此类对象,则该对象的属性“c”的显示将被省略。

class test():
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

    def __repr__(self):
        return 'test(%s, %s, %s)' % (self.a, self.b, self.c)


test1 = test("1", "abc", "def")
test2 = test("2", "yyy", "xxy")
test3 = test("3", "yyy", "xxy")

objList = [test1, test2, test3]

#takes out duplicate objects
new_list = [next(obj) for i, obj in
            groupby(sorted(objList, key=lambda test: test.a), lambda test: test.c)]
print(new_list)

上面的代码让我得到如下输出。

[test(1, abc, def), test(2, yyy, xxy)]

预期的输出是从对象中仅省略属性 c。

[test(1, abc, def), test(2, yyy, xxy),test(3, yyy)]

请帮忙!

【问题讨论】:

  • 由于您使用的是 repr,您将不得不在物理上失去对 self.c 的访问权限。或者更改 repr 函数。您是否有能力修改该类,或者解决方案是否需要与该示例类一起使用?
  • @deseuler,它是一个冻结的类,属性删除在那里基本上不起作用,因为frozeninstanceerror 会弹出错误
  • 如果不能修改 repr 方法,我想不出改变类打印方式的方法。这就是它的真正用途。不过,我会继续发布我的解决方案。它可能会敲响一些关于如何解决您的实际问题的钟声。
  • 让我在这里更清楚地说明我的问题,我只需要从冻结类的对象实例中取出重复的属性值,并且修改 repr 方法没有问题。

标签: python-3.x duplicates python-object


【解决方案1】:

更新了 REPR

为了能够更改类正在打印的内容,您必须能够更改 repr 方法。主要是因为呈现的内容有点过于狭隘。如果类如下,那么这是可能的:

class test():
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

    def __repr__(self):
      expr = []
      if self.a:
        expr.append(self.a)
      if self.b:
        expr.append(self.b)
      if self.c:
        expr.append(self.c)

      return 'test(%s)' % (', '.join(expr))

最大的障碍是我们需要对显示的内容进行一些控制,因此我们需要更改 repr 方法。或者,您可以通过利用 str 方法并在打印前转换为字符串来生成相同的结果。

类型无关的删除重复功能

由于我不知道您是确切的用例,并且想制作与所有类型的问题相关的东西,因此我制作了以下功能。它将允许您指定相等条件、满足条件时执行的操作以及如何对列表进行排序。

(默认检查后续值对象是否相等,如果相等则不包括结果列表中的第二个。)

def remove_dups(old_list, 
                condition=lambda a, b: a == b, 
                remove_func=lambda x, y: None, 
                sort_key=None):
  """
    Returns a new list that has duplicates removed from `old_list`

    #Arguments
    old_list: list to have duplicates discarded
    condition: test condition between previous and next obj to test equality.
    remove_func: what to add to the list if the condition is met. If `None` is returned
      then no value is added to the `new_list`
    sort_key: how to sort the `old_list`.
  """


  old_list = sorted(old_list, key=sort_key)
  comparitor = old_list[0] #used to compare previous and current obj
  new_list = [comparitor]
  for i, obj in enumerate(old_list[1:]):
    #if previous object and current obj are the same
    if condition(comparitor, obj):

      #run removal function
      if remove_func:
        new_value = remove_func(comparitor, obj)
      else:
        new_value = None

    else: #then objects are different, add the new one
      new_value = obj

    if new_value is not None:
      new_list.append(new_value)

    comparitor = obj
    new_value = None

  return new_list

您的案例(示例)

我们可以在您的情况下使用它,如下所示

test1 = test("1", "abc", "def")
test2 = test("2", "yyy", "xxy")
test3 = test("3", "yyy", "xxy")

objList = [test1, test2, test3]

#in lambda functions `a` corresponds to previous object in list,  
#`b` refers to currently observed object
new_list = remove_dups(objList,
            condition=lambda a, b: a.b == b.b, #if a.b and b.b the same
            remove_func=(lambda a, b: test(b.a, b.b, None)), #then set b.c = None
            sort_key=lambda obj: (obj.a, obj.b, obj.c)
          )

print(new_list) # [test(1, abc, def), test(2, yyy, xxy), test(3, yyy)]

编辑

如果您想在不编辑 repr 方法的情况下执行此操作,则可以使用 new_list 执行一些特殊的打印语句,而不是显式尝试打印测试对象。

例子:

objList = [test1, test2, test3]

#in lambda functions `a` corresponds to previous object in list,  
#`b` refers to currently observed object
new_list = remove_dups(objList,
            condition=lambda a, b: a.b == b.b, #if a.b and b.b the same
            remove_func=(lambda a, b: test(b.a, b.b, None)), #then set b.c = None
            sort_key=lambda obj: (obj.a, obj.b, obj.c)
          )

exprs = []
for test in new_list:
  expr = []
  if test.a:
    expr.append(test.a)
  if test.b:
    expr.append(test.b)
  if test.c:
    expr.append(test.c)

  exprs.append('test(%s)' % (', '.join(expr)))

print(exprs) # [test(1, abc, def), test(2, yyy, xxy), test(3, yyy)]

【讨论】:

  • 感谢@deseuler,帮了大忙!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-13
  • 1970-01-01
  • 2020-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多