python - 实现列表,字典嵌套去重(key去重,value去重)

本文介绍了一种使用Python进行列表去重的方法,包括基本列表及嵌套列表中的去重操作,并展示了如何通过比较特定键值来避免重复项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

摘自:http://m.blog.youkuaiyun.com/will130/article/details/50441937

t1 = [{'a':1}, {'a':2}, {'a':2}]
#dict([d.items()[0] for d in t1]).items()之外的部分纯粹是把列表内还原成一个字典
t2 = [{value:key} for key, value in dict([d.items()[0] for d in t1]).items()]
#! /usr/bin/env python
#coding=utf-8

class HostScheduler(object):

    def __init__(self, resource_list):

        self.resource_list = resource_list

    def MergeHost(self):
        allResource=[]
        allResource.append(self.resource_list[0])
        for dict in self.resource_list:
            #print len(l4)
            k=0
            for item in allResource:
                #print 'item'
                if dict['host'] != item['host']:
                    k=k+1
                    #continue
                else:
                    break
                if k == len(allResource):
                    allResource.append(dict)
        taskhost=[]
        for item in allResource:
            taskhost.append(item['host'])
        return taskhost



#该函数实现嵌套列表中,按某一元素去重复
def deleteRepeat():
    #1、列表中嵌套列表。按元素‘b’实现去重复
    l1=[['b',1],['b',2],['c',3],['a',1],['b',1],['b',1],]
    l2=[]
    l2.append(l1[0])
    for data in l1:
        #print len(l2)
        k=0
        for item in l2:
            #print 'item'
            if data[0] != item[0]:
                k=k+1
            else:
                break
            if k == len(l2):
                l2.append(data)
    print "l2: ",l2

    #2、列表中嵌套字典。按键值host实现去重复
    l3=[{'host':'compute21', 'cpu':2},{'host':'compute21', 'cpu':2},{'host':'compute22', 'cpu':2},
        {'host':'compute23', 'cpu':2},{'host':'compute22', 'cpu':2},{'host':'compute23', 'cpu':2},
        {'host':'compute24', 'cpu':2}]
    l4=[]
    l4.append(l3[0])
    for dict in l3:
        #print len(l4)
        k=0
        for item in l4:
            #print 'item'
            if dict['host'] != item['host']:
                k=k+1
                #continue
            else:
                break
            if k == len(l4):
                l4.append(dict)
    print "l4: ",l4


if __name__ == '__main__':
    #deleteRepeat()
    resource_list=[{'host':'compute21', 'cpu':2},{'host':'compute21', 'cpu':2},{'host':'compute22', 'cpu':2},
                   {'host':'compute23', 'cpu':2},{'host':'compute22', 'cpu':2},{'host':'compute23', 'cpu':2},
                   {'host':'compute24', 'cpu':2}]

    hostSchedule=HostScheduler(resource_list)
    taskhost=hostSchedule.MergeHost()
    print 'taskhost: '
    print taskhost

输出结果:

l2:  [['b', 1], ['c', 3], ['a', 1]]
l4:  [{'host': 'compute21', 'cpu': 2}, {'host': 'compute22', 'cpu': 2}, {'host': 'compute23', 'cpu': 2}, {'host': 'compute24', 'cpu': 2}]
taskhost: 
['compute21', 'compute22', 'compute23', 'compute24']
<think>我们面对的问题:如何对嵌套字典进行处理?嵌套字典是指字典的值可能又是一个字典(即字典嵌套字典)。的目标可能是:1.除整个嵌套字典复的子字典(即两个子字典内容完全相同)2.嵌套字典中某个键对应的复值(比如某个键对应的值是一个列表列表中有复的字典)但是,由于字典本身是可变且不可哈希的,我们不能直接将字典放入集合(set)中,因为集合要求元素是可哈希的。因此,我们需要将嵌套字典转换为可哈希的形式(例如元组或冻结的字典),然后进行。参考引用[2]提到:集合不能直接用于字典,因为字典是可变的,不可哈希。所以,我们需要一个策略:步骤1:将嵌套字典中的每一层字典转换为可哈希的类型(例如,将字典转换为元组,其中键值对按固定顺序排列)。步骤2:然后使用集合来。但是,的层次结构需要明确:是对整个嵌套字典(即整个嵌套结构作为一个整体),还是对内部某个键下的列表?根据用户的问题描述,用户希望的是“嵌套字典”,可能是指除整个嵌套字典复的子字典(即相同的子字典只保留一个)。例如,我们有一个字典,其值可能是字典,我们想确保没有两个相同的子字典。但是,嵌套字典的结构可能是这样的:{'key1':{'subkey1':value1,'subkey2':value2},'key2':{'subkey1':value1,'subkey2':value2},#这个和key1的相同'key3':{'subkey3':value3}}我们想要,使得每个子字典只出现一次(即key2,因为它的子字典key1的复)。但是,注意:在字典中,键(key)是唯一的,所以我们不能有两个相同的键。因此,这里复的是值(即子字典),而键不同。如果我们想除值复的项,那么我们可以创建一个新的字典,其中每个子字典只保留一次。但是,我们需要决定保留哪个键?通常,我们可以保留第一个出现的。另一种情况:嵌套字典的某个键对应的值是一个列表,而列表中有复的字典元素。这时我们需要对这个列表中的字典。由于问题没有明确,我们考虑两种情况:情况1:整个嵌套字典的值是字典,我们想要除值(即内层字典复的项。情况2:嵌套字典的某些键对应的值是一个字典列表,我们需要对这些列表中的字典。下面我们分别给出解决方案。情况1:除外层字典中值复的项(值是一个字典,且这个字典内容复)思路:遍历原始字典,记录已经出现过的内层字典(转换为可哈希的形式),如果当前内层字典已经出现过,则跳过,否则加入新字典。代码示例:defremove_duplicate_nested_dict(original_dict):seen=set()new_dict={}fork,vinoriginal_dict.items():#将内层字典v转换为可哈希的类型,例如将字典转换为一个元组,其中包含排序后的键值对元组#注意:如果内层字典的值可能也是不可哈希的(比如还有嵌套),我们需要递归转换。但用户问题中嵌套字典可能只有两层?#为了通用性,我们可以写一个函数将任意嵌套结构转换为可哈希的。#这里假设内层字典的值都是可哈希的(如数字、字符串、元组等),则我们可以:hashable_v=tuple(sorted(v.items()))ifhashable_vnotinseen:seen.add(hashable_v)new_dict[k]=vreturnnew_dict但是,如果内层字典的值又是一个字典(即多层嵌套),那么我们需要递归地转换整个嵌套结构为可哈希的。我们可以写一个函数将嵌套结构转换为可哈希的元组表示:defmake_hashable(o):ifisinstance(o,dict):returntuple(sorted((k,make_hashable(v))fork,vino.items()))elifisinstance(o,list)orisinstance(o,set):returntuple(make_hashable(e)foreino)else:returno#如果是可哈希的基本类型,则直接返回然后,在时使用这个函数。情况2:如果嵌套字典中某个键对应的值是一个列表,而列表中有复的字典元素,那么我们需要对这个列表。例如:data={'key1':[{'a':1},{'b':2},{'a':1}],#这里有两个相同的字典{'a':1}'key2':[{'c':3}]}我们想要对每个键对应的列表复的字典元素)。方法类似:defremove_duplicate_in_list(nested_dict):forkey,value_listinnested_dict.items():ifisinstance(value_list,list):#对列表中的每个元素,转换为可哈希的形式,然后,同时保留顺序(如果需要保留顺序的话)seen=set()new_list=[]foriteminvalue_list:#将item转换为可哈希hashable_item=make_hashable(item)ifhashable_itemnotinseen:seen.add(hashable_item)new_list.append(item)nested_dict[key]=new_listreturnnested_dict注意:上面的函数会修改原始字典,如果不希望修改,可以创建新的字典。由于用户的问题没有明确是哪种情况,我们可以提供两种情况的解决方案,并让用户根据实际数据结构选择。但是,用户的问题描述是“嵌套字典”,并且引用了引用[3](一个嵌套字典管理学生成绩的例子),在引用[3]中,嵌套字典的结构是:scores={'M1034':{'0001':88,'0002':85,'1002':90,'2000':92},...}这个结构是:外层字典的键是学生ID,值是一个字典(课程编号:分数)。这里,每个内层字典的键都是课程编号,值都是分数。那么,如果用户想,可能是指除外层字典中内层字典完全相同的项?即两个学生ID对应的成绩字典完全一样?这种情况很少见,因为学生ID不同,但成绩字典完全一样是有可能的。所以,我们按照情况1来处理。但是,在引用[3]的例子中,每个内层字典的键(课程编号)不同,所以内层字典通常不会复。所以用户可能是指另一种情况:内层字典的值(分数)有复?但这不是,而是复的分数?这显然不是。因此,我们需要澄清:嵌套字典的具体含义。然而,由于用户没有给出具体例子,我们只能提供通用的方法。综上所述,我们提供以下两种方法:方法一:针对整个嵌套字典的值(内层字典,保留唯一的内层字典(即如果有两个不同的键对应相同的内层字典,只保留一个键)。方法二:针对嵌套字典中值为列表的情况,对列表中的字典元素。下面我们分别用代码实现这两种方法,并假设嵌套结构是任意的(即可能有更深层的嵌套),我们使用递归转换函数。首先,定义一个递归转换函数,将任意嵌套结构转换为可哈希的结构(用于放入集合):</think>在Python中对嵌套字典进行处理时,需要解决字典不可哈希的核心问题。以下是两种实用的解决方案,基于将嵌套结构转换为可哈希对象实现: ### 方法1:递归冻结字典(推荐) 将嵌套字典递归转换为不可变的`namedtuple`或冻结字典,使其可哈希后放入集合: ```python from collections import namedtuple def freeze(d): """递归冻结嵌套字典为可哈希对象""" if isinstance(d, dict): # 创建动态namedtuple类型 sorted_items = sorted(d.items()) frozen_type = namedtuple('FrozenDict', [k for k, v in sorted_items]) return frozen_type(**{k: freeze(v) for k, v in sorted_items}) elif isinstance(d, list): return tuple(freeze(x) for x in d) return d # 基础类型直接返回 # 示例:对嵌套字典列表 nested_list = [ {'a': 1, 'b': {'x': [10, 20]}}, {'a': 1, 'b': {'x': [10, 20]}}, # 复项 {'c': [3, 4]} ] # 过程 seen = set() unique_list = [] for item in nested_list: frozen = freeze(item) if frozen not in seen: seen.add(frozen) unique_list.append(item) print(unique_list) # 输出: [{'a':1, 'b':{'x':[10,20]}}, {'c':[3,4]}] ``` ### 方法2:序列化字典为JSON字符串 利用JSON序列化将字典转为字符串实现: ```python import json def deduplicate_nested_dicts(dict_list): """通过JSON序列化嵌套字典列表""" seen = set() result = [] for d in dict_list: # 排序键保证序列化稳定 serialized = json.dumps(d, sort_keys=True) if serialized not in seen: seen.add(serialized) result.append(d) return result # 使用示例 data = [ {'user': {'id': 1, 'name': 'Alice'}}, {'user': {'id': 1, 'name': 'Alice'}}, # 复 {'user': {'id': 2, 'name': 'Bob'}} ] print(deduplicate_nested_dicts(data)) # 输出: [{'user': {'id':1, 'name':'Alice'}}, {'user': {'id':2, 'name':'Bob'}}] ``` ### 关键说明 1. **不可哈希问题** 字典不能直接作为集合元素或字典键,需转换为可哈希对象: - `freeze()`方法递归转换嵌套结构为`namedtuple` - JSON序列化生成唯一字符串标识 2. **保持原始顺序** 两种方法均使用列表追加顺序,避免`set()`的无序特性 3. **复杂度** - 时间复杂度:$O(n \cdot k)$,其中$k$是嵌套深度 - 空间复杂度:$O(n)$ 存储临时哈希对象 > 推荐优先使用`freeze()`方法,它在处理复杂嵌套结构时更高效,且保留类型信息。JSON方案适用于简单场景或需要持久化存储时[^1][^2]。 --- ### 相关问题 1. 当嵌套字典包含自定义类对象时,如何实现? 2. 在超大规模嵌套字典时,有哪些内存优化技巧? 3. 如何实现深度嵌套字典的差异对比(diff)操作? 4. 除了,还有哪些处理嵌套字典的高效技巧?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值