Python列表去重复项的N种方法,


说明

Python语言中列表(List)与其他语言的数组(Array)类似,是一种有序的集合数据结构,Python List可支持各种数据类型,长度也可动态调整,与JS中的数组或Java ArrayList很接近。在实际编程中,经常会遇到数组或列表去掉重复项,保持成员唯一性。实现方式有多种,比如新建列表来存储非重复项,或者在原有基础上删除掉重复的项,也可以利用数据结构来达到去重复。具体哪一种方法更好呢?以下约20种方式都可以实现,我们可以通过这些来交流和学习。

Python列表去重复项的N种方法

方式

  1. ## 1. 新建列表,如果新列表中不存在,则添加到新列表。 
  2. def unique(data): 
  3.     new_list = [] 
  4.     for item in data: 
  5.         if item not in new_list: 
  6.             new_list.append(item) 
  7.     return new_list 
  8.  
  9.  
  10. # test 
  11. data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1] 
  12. start_time = time.time() 
  13. print("new_list + not in data:", unique(data)) 
  14. print("time:" + str((time.time() - start_time) * 1000) + " ms") 
  15.  
  16. # result 
  17. $ python -V 
  18. Python 2.7.16 
  19. $ python unique.py  
  20. ('for list + not in. data:', ['a', 1, 2, 'b']) 
  21. time:0.0441074371338 ms 
  22.  
  23. ## 2. 新建列表。根据下标判断是否存在新列表中,如果新列表中不存在则添加到新列表。 
  24. def unique(data): 
  25.     new_list = [] 
  26.     for i in range(len(data)): 
  27.         if data[i] not in new_list: 
  28.             new_list.append(data[i]) 
  29.     return new_list 
  30.  
  31.  
  32. ## 2.1 新建列表,使用列表推导来去重。是前一种的简写。 
  33. def unique(data): 
  34.     new_list = [] 
  35.     [new_list.append(i) for i in data if not i in new_list] 
  36.     return new_list 
  37.  
  38. # test 
  39. data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1] 
  40. start_time = time.time() 
  41. print("for range + not in. data:", unique(data)) 
  42. print("time:" + str((time.time() - start_time) * 1000) + " ms") 
  43.  
  44. ## 3. 通过index找不到该项,则追加到新列表中。index找不到会报错,因此放在异常处理里。 
  45. def unique(data): 
  46.     new_list = [] 
  47.     for i in range(len(data)): 
  48.         item = data[i] 
  49.         try: 
  50.             if (new_list.index(item) < 0): 
  51.                 print('new_list:', new_list) 
  52.         except ValueError: 
  53.             new_list.append(item) 
  54.     return new_list 
  55.  
  56.  
  57. # test 
  58. data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1] 
  59. start_time = time.time() 
  60. print("list index + except:", unique(data)) 
  61. print("time:" + str((time.time() - start_time) * 1000) + " ms") 
  62.  
  63. ## 4. 新建列表,两个循环。如果内循环与外循环项相同,且下标相同就添加到新列表,其余忽略 
  64. def unique(data): 
  65.     new_list = [] 
  66.     for i in range(len(data)): 
  67.         j = 0 
  68.         while j <= i: 
  69.             if data[i] == data[j]: 
  70.                 if i == j: 
  71.                     new_list.append(data[i]) 
  72.                 break 
  73.             j += 1 
  74.     return new_list 
  75.  
  76. # test 
  77. data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1] 
  78. start_time = time.time() 
  79. print("new list + for. new_list:", unique(data)) 
  80. print("time:" + str((time.time() - start_time) * 1000) + " ms") 
  81.  
  82. ## 5. 在原有列表上移除重复项目。自后往前遍历,逐个与前面项比较,如果值相同且下标相同,则移除当前项。 
  83. def unique(data): 
  84.     l = len(data) 
  85.     while (l > 0): 
  86.         l -= 1 
  87.         i = l 
  88.         while i > 0: 
  89.             i -= 1 
  90.             if data[i] == data[l]: 
  91.                 del data[l] 
  92.                 break 
  93.     return data 
  94.  
  95. # test 
  96. data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1] 
  97. start_time = time.time() 
  98. print("one list while. last -> first result. data:", unique(data)) 
  99. print("time:" + str((time.time() - start_time) * 1000) + " ms") 
  100.  
  101. ## 6. 在原有列表上移除重复项目。自前往后遍历,逐个与后面项比较,如果值相同且下标相同,则移除当前项。 
  102. def unique(data): 
  103.     l = len(data) 
  104.     i = 0 
  105.     while i < l: 
  106.         j = i + 1 
  107.         while j < l: 
  108.             if data[i] == data[j]: 
  109.                 del data[j] 
  110.                 l -= 1 
  111.                 i -= 1 
  112.                 break 
  113.             j += 1 
  114.         i += 1 
  115.     return data 
  116.  
  117.  
  118. # test 
  119. data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1] 
  120. start_time = time.time() 
  121. print("one list while. first -> last result. data:", unique(data)) 
  122. print("time:" + str((time.time() - start_time) * 1000) + " ms") 
  123.  
  124. ## 7. 新建列表。遍历列表,利用index比较出现的位置,如果出现在第一次的位置则追加到新数组。 
  125. def unique(data): 
  126.     new_list = [] 
  127.     for i in range(len(data)): 
  128.         if i == data.index(data[i]): 
  129.             new_list.append(data[i]) 
  130.     return new_list 
  131.  
  132.  
  133. # test 
  134. data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1] 
  135. start_time = time.time() 
  136. print("for range + index. data:", unique(data)) 
  137. print("time:" + str((time.time() - start_time) * 1000) + " ms") 
  138.  
  139. ## 8. 利用字典属性唯一性来实现去重复。 
  140. def unique(data): 
  141.     obj = {} 
  142.     for item in data: 
  143.         obj[item] = item 
  144.     return obj.values() 
  145.  
  146.  
  147. # test 
  148. data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1] 
  149. start_time = time.time() 
  150. print("list + dict:", unique(data)) 
  151. print("time:" + str((time.time() - start_time) * 1000) + " ms") 
  152.  
  153. ## 或者直接通过dict.fromkeys来实现 
  154. print("dict fromkeys:", dict.fromkeys(data).keys()) 
  155.  
  156. ## 9. 利用filter函数,即把不符合条件的过滤掉。这里filter不支持下标,因此需要借助外部列表存储不重复项 
  157. def uniq(item): 
  158.     i = data.index(item) 
  159.     if (item not in new_list): 
  160.         new_list.append(item) 
  161.         return True 
  162.     return False 
  163. def unique(item): 
  164.     if obj.get(item) == None: 
  165.         obj[item] = item 
  166.         return True 
  167.     return False 
  168.  
  169.  
  170. # test 
  171. data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1] 
  172. start_time = time.time() 
  173. new_list = [] 
  174. print('filter + list + not in: ', filter(uniq, data)) 
  175. print("time:" + str((time.time() - start_time) * 1000) + " ms") 
  176.  
  177. ## 10. 利用字典结合过滤来实现去重复。 
  178. def unique(item): 
  179.     if obj.get(item) == None: 
  180.         obj[item] = item 
  181.         return True 
  182.     return False 
  183.  
  184.  
  185. # test 
  186. data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1] 
  187. start_time = time.time() 
  188. obj = {} 
  189. print("filter + dict + get:", filter(unique, data)) 
  190. print("time:" + str((time.time() - start_time) * 1000) + " ms") 
  191.  
  192. ## 11. 利用map来实现去重复。与map与filter类似,是一个高阶函数。可以针对其中项逐个修改操作。 
  193. ## 与filter不同map会保留原有项目,并不会删除,因此值可以改为None,然后再过滤掉。 
  194. def unique(item): 
  195.     if item not in new_list: 
  196.         new_list.append(item) 
  197.         return item 
  198.     return None 
  199.  
  200.  
  201. # test 
  202. data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1] 
  203. new_list = [] 
  204. start_time = time.time() 
  205.  
  206. print("list from Map:", filter(lambda item: item != None, map(unique, data))) 
  207. print("time:" + str((time.time() - start_time) * 1000) + " ms") 
  208.  
  209. ## 12. 利用set数据结构里key的唯一性来去重复 
  210. data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1] 
  211. print("from Set:", list(set(data))) 
  212. print("time:" + str((time.time() - start_time) * 1000) + " ms") 
  213.  
  214. ## 13. 提前排序,从后向前遍历,将当前项与前一项对比,如果重复则移除当前项 
  215. def unique(data): 
  216.     data.sort() 
  217.     l = len(data) 
  218.     while (l > 0): 
  219.         l -= 1 
  220.         if (data[l] == data[l - 1]): 
  221.             data.remove(data[l]) 
  222.     return data 
  223.  
  224.  
  225. # test 
  226. data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1] 
  227. start_time = time.time() 
  228. print("sort + remove:", unique(data)) 
  229. print("time:" + str((time.time() - start_time) * 1000) + " ms") 
  230.  
  231. ## 14. 提前排序,自前往后遍历,将当前项与后一项对比,如果重复则移除当前项 
  232. def unique(data): 
  233.     """ 
  234.      in python 3: TypeError: '<' not supported between instances of 'int' and 'str' 
  235.      need to keep the same Type of member in List 
  236.     """ 
  237.     data.sort() 
  238.     l = len(data) - 1 
  239.     i = 0 
  240.     while i < l: 
  241.         if (data[i] == data[i + 1]): 
  242.             del data[i] 
  243.             i -= 1 
  244.             l -= 1 
  245.         i += 1 
  246.     return data 
  247.  
  248.  
  249. # test 
  250. data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1] 
  251. start_time = time.time() 
  252. print("sort+del ASE:", unique(data)) 
  253. print("time:" + str((time.time() - start_time) * 1000) + " ms") 
  254.  
  255. ## 15. 利用reduce函数来去重复。reduce具有累计的作用,判断如果不在累计结果中出现,则追加到结果中。 
  256. import functools 
  257.  
  258.  
  259. def unique(data): 
  260.     new_list = [] 
  261.  
  262.     def foo(result, item): 
  263.         if isinstance(result, list) == False: 
  264.             result = [result] 
  265.         return result if item in result else result + [item] 
  266.  
  267.     return functools.reduce(foo, data) 
  268.  
  269.  
  270. # test 
  271. data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1] 
  272. start_time = time.time() 
  273. print("functools.reduce:", unique(data)) 
  274. print("time:" + str((time.time() - start_time) * 1000) + " ms") 
  275.  
  276. ## 16. 利用递归调用来去重复。递归自后往前逐个调用,当长度为1时终止。 
  277. ## 当后一项与前任一项相同说明有重复,则删除当前项。相当于利用自我调用来替换循环 
  278. def recursion_unique(data, len): 
  279.     if (len <= 1): 
  280.         return data 
  281.  
  282.     l = len 
  283.     last = l - 1 
  284.     is_repeat = False 
  285.  
  286.     while (l > 1): 
  287.         l -= 1 
  288.         if (data[last] == data[l - 1]): 
  289.             is_repeat = True 
  290.             break 
  291.  
  292.     if (is_repeat): 
  293.         del data[last] 
  294.  
  295.     return recursion_unique(data, len - 1) 
  296.  
  297.  
  298. # test 
  299. data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1] 
  300. start_time = time.time() 
  301. print("recursion_unique:", recursion_unique(data, len(data))) 
  302. print("time:" + str((time.time() - start_time) * 1000) + " ms") 
  303.  
  304. ## 17. 利用递归调用来去重复的另外一种方式。递归自后往前逐个调用,当长度为1时终止。 
  305. ## 与上一个递归不同,这里将不重复的项目作为结果拼接起来 
  306. def recursion_unique_new(data, len): 
  307.     if (len <= 1): 
  308.         return data 
  309.  
  310.     l = len 
  311.     last = l - 1 
  312.     is_repeat = False 
  313.     while (l > 1): 
  314.         l -= 1 
  315.         if (data[last] == data[l - 1]): 
  316.             is_repeat = True 
  317.             break 
  318.  
  319.     if (is_repeat): 
  320.         del data[last:] 
  321.         result = [] 
  322.     else: 
  323.         result = [data[last]] 
  324.  
  325.     return recursion_unique_new(data, len - 1) + result 
  326.  
  327.  
  328. # test 
  329. data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1] 
  330. start_time = time.time() 
  331. print("recursion_unique_new:", recursion_unique_new(data, len(data))) 
  332. print("time:" + str((time.time() - start_time) * 1000) + " ms") 
  333.  
  334. ## 18. 利用numpy lib库. 需提前安装 `pip install numpy` 
  335. import numpy as np 
  336.  
  337.  
  338. def unique(data): 
  339.     res = np.array(data) 
  340.     return list(np.unique(res)) 
  341.  
  342.  
  343. # test 
  344. data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1] 
  345. start_time = time.time() 
  346. print("import numpy as np.unique:", unique(data)) 
  347. print("time:" + str((time.time() - start_time) * 1000) + " ms") 
Python列表去重复项的N种方法

讨论

从以上例子上可以看出,相对来讲,Python比起其它语言要灵活得多,与JS并列最流行的脚本类语言,这也就是为何Python如此流行的原因吧。

哪一种方式更适合呢?你常用那种方式来实现去重复项?新建数组、非新建、借助Dict或Set等结构,亦或是其它方式?

Python列表去重复项的N种方法

评论关闭