猿问

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

任务:


开发一个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_lst


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

结果:


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

但是我怎样才能恢复原来的顺序呢?


慕斯王
浏览 155回答 3
3回答

蝴蝶不菲

这里有两个问题,所以为了回答的目的,我将两者都列出来。尊重类型(你已经想通了)删除列表中的重复项建议将中间体构造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 collectionsunique_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)        #mine38.6 ms ± 179 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)In [34]: timeit ordereddict_fromkeys(l)  #mine with OrderedDict53.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's46.8 ms ± 377 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)In [30]: timeit listcompr_side_effect(l)  #CDJB's55.5 ms ± 801 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

Helenr

放入集合,检查集合的方法很好。您还可以将 anydict()用于 python 3.7+(键保持输入有序)或OrderedDict用于 3.7 以下的 python 版本:def clean_list(list_to_clean):&nbsp; &nbsp; ord_dic = dict&nbsp; &nbsp; import sys&nbsp; &nbsp; major,minor,_,_,_ = sys.version_info&nbsp; &nbsp; if major < 3 or major == 3 and minor < 7:&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; # dict not yet input ordered&nbsp; &nbsp; &nbsp; &nbsp; from collections import OrderedDict&nbsp; &nbsp; &nbsp; &nbsp; no_dubl_lst = OrderedDict(((type(a),a),None) for a in list_to_clean)&nbsp; &nbsp; else:&nbsp; &nbsp; &nbsp; &nbsp; # dict is input ordered by default&nbsp; &nbsp; &nbsp; &nbsp; no_dubl_lst = dict(((type(a),a),None) for a in list_to_clean)&nbsp; &nbsp; return list(b for _,b in no_dubl_lst.keys()) # only produce the actual dataprint(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):&nbsp; &nbsp; &nbsp; &nbsp; # dict is input ordered by default&nbsp; &nbsp; &nbsp; &nbsp; no_dubl_lst = dict(((type(a),a),None) for a in list_to_clean)类似于ivan_pozdeev答案 - 在我创建答案时,他删除/编辑/取消删除了他的第一个内容更多的内容。你会得到我的自动版本检测,所以不要删除它。

喵喔喔

你试试这个。就像你问的第一个实例仍然在原地休息被删除。(注意这个是O(n^2))_list=[32, 32.1, 32.0, -32, 32, '32']_clist=[]for i in _list:&nbsp; &nbsp; if (i,type(i),) not in _clist:&nbsp; &nbsp; &nbsp; &nbsp; _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:&nbsp; &nbsp; if (i,type(i),) not in unique:&nbsp; &nbsp; &nbsp; &nbsp; unique.add((i,type(i),))&nbsp; &nbsp; &nbsp; &nbsp; cleaned.append(i)笔记:请查看ivan_pozdeev的答案以timeit分析已发布的几个答案。
随时随地看视频慕课网APP

相关分类

Python
我要回答