如何忽略显示中的重复对象值

How to ignore duplicate object values from display

我有一个测试 class 有 3 个属性 a、b 和 c。 class 的 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)

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

[测试(1, abc, def), 测试(2, yyy, xxy)]

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

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

请帮忙!

已更新 REPR

要能够更改 class 正在打印的内容,您必须能够更改 repr 方法。主要是呈现的东西有点太拘束了。相反,如果 class 如下所示,那么这是可能的:

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