面试python开发岗,经常会碰到这样一道面试题,列表去重问题。其在爬虫项目中会得到广泛应用。下面列出几个方法:
1. 利用集合元素唯一性的性质:
def DelDupli(L):
return list(set(L))
L = [1,3,3,3,4,3,34,3,54,3,4,2,8]
print(DelDupli(L))
# result
[1, 34, 3, 4, 2, 8, 54]
2. 创建一个新列表,判断原列表中的每个元素是否在新列表中,不在的话追加即可:
def DelDupli2(L):
lst = [] # 空间复杂度会增加
for x in L:
if x not in lst:
lst.append(x)
return lst
L = [1,3,3,3,4,3,34,3,54,3,4,2,8]
print(DelDupli2(L))
# result
[1, 3, 4, 34, 54, 2, 8]
3. 利用字典“键”的唯一性解决该问题:
def DelDupli3(L):
myDict = {}
for i in L:
myDict[i] = 0
L = list(myDict.keys())
return L
L = [1,3,3,3,4,3,34,3,54,3,4,2,8]
print(DelDupli3(L))
# result
[1, 3, 4, 34, 54, 2, 8]
上面方法2和方法3都需要创建新对象,如果数据量过大,会增加算法的空间复杂度,不可取。
4. 遍历列表,统计当前元素在列表中的个数,若大于1,则去除:
def DelDupli4(L):
for i in L:
if L.count(i) > 1:
L.remove(i)
return L
L = [1,3,3,3,4,3,34,3,54,3,4,2,8]
print(DelDupli4(L))
# result
[1, 4, 34, 54, 3, 4, 2, 8]
【注意】该方法是一个典型错误!
i 相当于是按照列表的下标来取值,每循环完一次,下标 i 会自动加1,这样便会跳过一些元素的判断,从而导致错误。
可附加一些调试信息,这样看的会更清楚一点:
def DelDupli4(L):
for i in L:
print('L ---> ', L)
print('i ---> ', i)
if L.count(i) > 1:
L.remove(i)
return L
L = [1, 3, 3, 3, 4, 3, 34, 3, 54, 3, 4, 2, 8]
print(DelDupli4(L))
# result
L ---> [1, 3, 3, 3, 4, 3, 34, 3, 54, 3, 4, 2, 8]
i ---> 1
L ---> [1, 3, 3, 3, 4, 3, 34, 3, 54, 3, 4, 2, 8]
i ---> 3
L ---> [1, 3, 3, 4, 3, 34, 3, 54, 3, 4, 2, 8]
i ---> 3
L ---> [1, 3, 4, 3, 34, 3, 54, 3, 4, 2, 8]
i ---> 3
L ---> [1, 4, 3, 34, 3, 54, 3, 4, 2, 8]
i ---> 3
L ---> [1, 4, 34, 3, 54, 3, 4, 2, 8]
i ---> 3
L ---> [1, 4, 34, 54, 3, 4, 2, 8]
i ---> 2
L ---> [1, 4, 34, 54, 3, 4, 2, 8]
i ---> 8
[1, 4, 34, 54, 3, 4, 2, 8]
5. 为解决上述问题,其实也很简单,只需将 if 语句变成 while 语句即可。使用 while 可循环判断当前下标的元素个数是否大于1,这样便不会导致跳过某个元素的情况发生。
def DelDupli5(L):
for i in L:
while L.count(i) > 1:
L.remove(i)
return L
L = [1,3,3,3,4,3,34,3,54,3,4,2,8]
print(DelDupli5(L))
# result
[1, 34, 54, 3, 4, 2, 8]