为了账号安全,请及时绑定邮箱和手机立即绑定

从列表中删除重复项,但考虑元素的类型并保留顺序

从列表中删除重复项,但考虑元素的类型并保留顺序

慕斯王 2022-07-12 10:31:11
任务:开发一个clean_list (list_to_clean)函数,它接受 1 个参数 - 任意长度的任意值(字符串、整数和浮点数)的列表,并返回一个具有相同值但没有重复项的列表。这意味着如果原始列表中存在多个实例中的值,则该值的第一个“实例”保留在原地,第二个、第三个等被删除。例子:函数调用:clean_list ([32, 32.1, 32.0, -32, 32, '32']) 返回:[32, 32.1, 32.0, -32, '32']我的代码:def clean_list(list_to_clean):   no_dubl_lst = [value for _, value in set((type(x), x) for x in list_to_clean)]   return no_dubl_lstprint(clean_list([32, 32.1, 32.0, -32, 32, '32']))结果:[32.1, 32, -32, 32.0, '32']但是我怎样才能恢复原来的顺序呢?
查看完整描述

3 回答

?
蝴蝶不菲

TA贡献1810条经验 获得超4个赞

这里有两个问题,所以为了回答的目的,我将两者都列出来。


尊重类型(你已经想通了)

删除列表中的重复项建议将中间体构造set为最快的方法。如果一个元素等于当前元素,则认为它存在于集合中。


在您的情况下,您不仅需要相等的值,还需要相等的类型。那么为什么不构造一个中间元组(value, type)呢?


unique_list = [v for v,t in {(v,type(v)) for v in orig_list}]

维持秩序

根据Python 是否有有序集,使用“有序集”容器?. 例如:


从 3.7 开始(以及 CPython 3.6,这是一个实现细节),常规dicts 保留插入顺序:


unique_list = [v for v,t in dict.fromkeys((v,type(v)) for v in orig_list)]

对于所有版本(也存在于 3.6+ 中,因为它具有其他方法),请使用collections.OrderedDict:


import collections

unique_list = [v for v,t in collections.OrderedDict.fromkeys((v,type(v)) for v in orig_list)]

作为参考,timeit我的机器(3.7.4 win64)上的结果与撰写本文时的其他答案相比:


In [24]: l=[random.choice((int,float,lambda v:str(int(v))))(random.random()*1000) for _ in range(100000)]


In [26]: timeit dict_fromkeys(l)        #mine

38.6 ms ± 179 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)


In [34]: timeit ordereddict_fromkeys(l)  #mine with OrderedDict

53.3 ms ± 233 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)


In [25]: timeit build_with_filter(l)    #Ch3steR's O(n)

48.7 ms ± 214 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)


In [28]: timeit dict_with_none(l)       #Patrick Artner's

46.8 ms ± 377 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)


In [30]: timeit listcompr_side_effect(l)  #CDJB's

55.5 ms ± 801 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)


查看完整回答
反对 回复 2022-07-12
?
Helenr

TA贡献1780条经验 获得超4个赞

放入集合,检查集合的方法很好。您还可以将 anydict()用于 python 3.7+(键保持输入有序)或OrderedDict用于 3.7 以下的 python 版本:


def clean_list(list_to_clean):

    ord_dic = dict


    import sys

    major,minor,_,_,_ = sys.version_info


    if major < 3 or major == 3 and minor < 7: 

        # dict not yet input ordered

        from collections import OrderedDict

        no_dubl_lst = OrderedDict(((type(a),a),None) for a in list_to_clean)

    else:

        # dict is input ordered by default

        no_dubl_lst = dict(((type(a),a),None) for a in list_to_clean)



    return list(b for _,b in no_dubl_lst.keys()) # only produce the actual data


print(clean_list([32, 32.1, 32.0, -32, 32, '32']))

生产:


[32, 32.1, 32.0, -32, '32']

本质上,dict-keys 的行为就像在一个集合中一样(只会使用第一个,后面的会覆盖None第一个的值) - 但它们是有序的。


如果您在 3.7+ 上简单使用


def clean_list(list_to_clean):

        # dict is input ordered by default

        no_dubl_lst = dict(((type(a),a),None) for a in list_to_clean)

类似于ivan_pozdeev答案 - 在我创建答案时,他删除/编辑/取消删除了他的第一个内容更多的内容。


你会得到我的自动版本检测,所以不要删除它。


查看完整回答
反对 回复 2022-07-12
?
喵喔喔

TA贡献1735条经验 获得超5个赞

你试试这个。


就像你问的第一个实例仍然在原地休息被删除。

(注意这个是O(n^2))


_list=[32, 32.1, 32.0, -32, 32, '32']

_clist=[]

for i in _list:

    if (i,type(i),) not in _clist:

        _clist.append((i,type(i),))

cleaned_list=list(zip(*_clist))[0]

print(cleaned_list)

#(32, 32.1, 32.0, -32, '32')

一种O(n)具有额外O(n)空间的方法。


_list=[32, 32.1, 32.0, -32, 32, '32']

unique=set()

cleaned=[]

for i in _list:

    if (i,type(i),) not in unique:

        unique.add((i,type(i),))

        cleaned.append(i)

笔记:


请查看ivan_pozdeev的答案以timeit分析已发布的几个答案。


查看完整回答
反对 回复 2022-07-12
  • 3 回答
  • 0 关注
  • 120 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号