【问题标题】:Remove duplicate JSON objects from list in python从python中的列表中删除重复的JSON对象
【发布时间】:2016-03-01 12:40:55
【问题描述】:

我有一个特定值重复多次的 dict 列表,我想删除重复值。

我的清单:

te = [
      {
        "Name": "Bala",
        "phone": "None"
      },
      {
        "Name": "Bala",
        "phone": "None"
      },
      {
        "Name": "Bala",
        "phone": "None"
      },
      {
        "Name": "Bala",
        "phone": "None"
      }
    ]

删除重复值的功能:

def removeduplicate(it):
    seen = set()
    for x in it:
        if x not in seen:
            yield x
            seen.add(x)

当我调用这个函数时,我得到generator object

<generator object removeduplicate at 0x0170B6E8>

当我尝试迭代生成器时,我得到TypeError: unhashable type: 'dict'

有没有办法删除重复值或迭代生成器

【问题讨论】:

  • 您不能将字典添加到集合中,要添加到集合中的内容必须是可散列的。
  • 附带说明:这不是“JSON 对象列表”,而是字典列表。 没有 JSON 对象这样的东西 - JSON 是一种文本格式,而不是一种对象...

标签: python json list dictionary generator


【解决方案1】:

您可以通过字典理解轻松删除重复键,因为字典不允许重复键,如下 -

te = [
      {
        "Name": "Bala",
        "phone": "None"
      },
      {
        "Name": "Bala",
        "phone": "None"
      },
      {
        "Name": "Bala",
        "phone": "None"
      },
      {
        "Name": "Bala",
        "phone": "None"
      },
      {
          "Name": "Bala1",
          "phone": "None"
      }      
    ]

unique = { each['Name'] : each for each in te }.values()

print unique

输出-

[{'phone': 'None', 'Name': 'Bala1'}, {'phone': 'None', 'Name': 'Bala'}]

【讨论】:

  • 真的很好,我会把它放在我的口袋里。 OTOH 请注意,这与 OP 的功能并不完全相同,因为他正在检查完整的字典,在您的情况下,您将丢弃任何具有相同名称的字典,无论是否不同。
  • 其实经过测试,会更像这样:unique = { repr(each): each for each in te }.values()
  • OP 已接受它,但我不确定这个答案是否正确,因为它用后来的 dicts 替换(来自列表 te)以前的 dicts,即它丢失了数据。例如。如果te 包含另一个字典{'Name': 'Bala', 'phone': '1234'},则仅保留te 中名称为Bala 的最后一项。
【解决方案2】:

因为您无法将dict 添加到set。来自this question

您正在尝试使用dict 作为另一个dictset 的密钥。这不起作用,因为密钥必须是可散列的。

作为一般规则,只有不可变对象(字符串、整数、浮点数、冻结集、不可变元组)是可散列的(尽管可能存在例外)。

>>> foo = dict()
>>> bar = set()
>>> bar.add(foo)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>> 

相反,您已经在使用if x not in seen,所以只需使用一个列表:

>>> te = [
...       {
...         "Name": "Bala",
...         "phone": "None"
...       },
...       {
...         "Name": "Bala",
...         "phone": "None"
...       },
...       {
...         "Name": "Bala",
...         "phone": "None"
...       },
...       {
...         "Name": "Bala",
...         "phone": "None"
...       }
...     ]

>>> def removeduplicate(it):
...     seen = []
...     for x in it:
...         if x not in seen:
...             yield x
...             seen.append(x)

>>> removeduplicate(te)
<generator object removeduplicate at 0x7f3578c71ca8>

>>> list(removeduplicate(te))
[{'phone': 'None', 'Name': 'Bala'}]
>>> 

【讨论】:

    【解决方案3】:

    您仍然可以使用set 进行重复检测,只需将字典转换为可散列的内容,例如tuple。您的字典可以通过tuple(d.items()) 转换为元组,其中d 是字典。将其应用于您的生成器功能:

    def removeduplicate(it):
        seen = set()
        for x in it:
            t = tuple(x.items())
            if t not in seen:
                yield x
                seen.add(t)
    
    >>> for d in removeduplicate(te):
    ...    print(d)
    {'phone': 'None', 'Name': 'Bala'}
    
    >>> te.append({'Name': 'Bala', 'phone': '1234567890'})
    >>> te.append({'Name': 'Someone', 'phone': '1234567890'})
    
    >>> for d in removeduplicate(te):
    ...    print(d)
    {'phone': 'None', 'Name': 'Bala'}
    {'phone': '1234567890', 'Name': 'Bala'}
    {'phone': '1234567890', 'Name': 'Someone'}
    

    这提供了比“看到”list (O(n)) 更快的查找(平均 O(1))。是否值得将每个字典转换为元组的额外计算取决于您拥有的字典数量以及有多少重复项。如果有很多重复项,“已看到”list 将变得非常大,并且测试是否已看到 dict 可能会成为一项昂贵的操作。这可能证明元组转换是合理的 - 您必须对其进行测试/分析。

    【讨论】:

      猜你喜欢
      • 2011-03-15
      • 1970-01-01
      • 2023-03-06
      • 2012-04-03
      • 2019-04-07
      • 2017-06-23
      • 1970-01-01
      相关资源
      最近更新 更多