如何在python中使独特的嵌套字典列表

时间:2014-12-09 08:22:34

标签: python list dictionary unique python-2.6

我有以下嵌套词典列表:

[{'permission': 'full',
  'permission_type': 'allow',
  'trustee': {'id': 'SID:S-1-5-32-545',
              'name': 'Users',
              'type': 'group'}},
 {'permission': 'full',
  'permission_type': 'allow',
  'trustee': {'id': 'SID:S-1-5-32-545',
              'name': 'Users',
              'type': 'group'}},
 {'permission': 'full',
  'permission_type': 'allow',
  'trustee': {'id': 'SID:S-1-5-32-544',
              'name': 'Administrators',
              'type': 'group'}}]

我想让它独一无二,并尝试了不同的建议但没有成功。 有人可以帮助它在python 2.6中独一无二吗?上面的数据中没有关键/唯一字段。 我希望得到以下结果(列表的一个成员作为完整副本被删除):

[{'permission': 'full',
  'permission_type': 'allow',
  'trustee': {'id': 'SID:S-1-5-32-545',
              'name': 'Users',
              'type': 'group'}},
 {'permission': 'full',
  'permission_type': 'allow',
  'trustee': {'id': 'SID:S-1-5-32-544',
              'name': 'Administrators',
              'type': 'group'}}]

2 个答案:

答案 0 :(得分:5)

你需要跟踪你是否已经看过字典。遗憾的是,字典不可删除,并且不跟踪顺序,因此您需要将字典转换为 可以删除的字典。一个frozenset()键值对(作为元组)会做,但是你需要递归地压扁:

def set_from_dict(d):
    return frozenset(
        (k, set_from_dict(v) if isinstance(v, dict) else v)
        for k, v in d.iteritems())

这些frozenset()个对象代表足以跟踪唯一项目的字典值:

seen = set()
result = []
for d in inputlist:
    representation = set_from_dict(d)
    if representation in seen:
        continue
    result.append(d)
    seen.add(representation)

这会保留输入列表的原始顺序,减去重复项。如果您使用的是Python 2.7及更高版本,OrderedDict在这里会有所帮助,但您使用的是Python 2.6,所以我们需要稍微详细一点。

上述方法需要O(N)时间,每个输入字典一步,因为针对集合的测试只需要O(1)常数时间。

演示:

>>> inputlist = [{'permission': 'full',
...   'permission_type': 'allow',
...   'trustee': {'id': 'SID:S-1-5-32-545',
...               'name': 'Users',
...               'type': 'group'}},
...  {'permission': 'full',
...   'permission_type': 'allow',
...   'trustee': {'id': 'SID:S-1-5-32-545',
...               'name': 'Users',
...               'type': 'group'}},
...  {'permission': 'full',
...   'permission_type': 'allow',
...   'trustee': {'id': 'SID:S-1-5-32-544',
...               'name': 'Administrators',
...               'type': 'group'}}]
>>> def set_from_dict(d):
...     return frozenset(
...         (k, set_from_dict(v) if isinstance(v, dict) else v)
...         for k, v in d.iteritems())
... 
>>> seen = set()
>>> result = []
>>> for d in inputlist:
...     representation = set_from_dict(d)
...     if representation in seen:
...         continue
...     result.append(d)
...     seen.add(representation)
... 
>>> from pprint import pprint
>>> pprint(result)
[{'permission': 'full',
  'permission_type': 'allow',
  'trustee': {'id': 'SID:S-1-5-32-545', 'name': 'Users', 'type': 'group'}},
 {'permission': 'full',
  'permission_type': 'allow',
  'trustee': {'id': 'SID:S-1-5-32-544',
              'name': 'Administrators',
              'type': 'group'}}]

答案 1 :(得分:1)

您的商品为dict,因此您无法直接使用set(请查看冻结集或this question/answer)。 但你仍然可以比较这些项目:

>>> l[0]==l[1]
True
>>> l[0]==l[2]
False

如果元素尚未存在,只需将其添加到新列表中即可:

>>> l2=[]
>>> for i in l:
...   if i not in l2:
...     l2.append(i)
...
>>> pprint(l2)
[{'permission': 'full',
  'permission_type': 'allow',
  'trustee': {'id': 'SID:S-1-5-32-545', 'name': 'Users', 'type': 'group'}},
 {'permission': 'full',
  'permission_type': 'allow',
  'trustee': {'id': 'SID:S-1-5-32-544',
              'name': 'Administrators',
              'type': 'group'}}]