如何从python中的列表中删除重复的条目

时间:2014-11-08 00:42:56

标签: python algorithm sorting hashmap

最近在一次采访中,我被要求编写一个python代码来删除列表中的所有重复条目。

例如:

Input List = {1,2,4,5,2,3,1}
Expected Output List = {4,5,3}

在上面的例子中,1& s& 2出现不止一次,应将其删除。订单保存很重要。这就是问题。

他再次不希望我使用set(),unique()等内置函数。我猜他正在测试我的算法和ds技能。他在一开始就说清楚了。

我当场想到了两种方法。 1.)排序(nlog(n)的复杂性) 2.)HashTable(排序更快)

HashTable方法:

arr = [1,2,4,5,2,3,1]

//function : to create a hash table with key = arr[i] & value = occurence count
def dataCountTable(arr):
    countTable = {}
    i = 0
    while i<len(arr) :
        if arr[i] in countTable : 
            countTable[arr[i]] += 1
        else :
        countTable[arr[i]] = 1
    i+=1
return countTable

//function : to remove duplicates using the arr & hash table
def rmvAllDuplicate(arr, countTable):
    outList = list()
    i = 0
    while i<len(arr) :
        if countTable[arr[i]] == 1 :
            outList.append(arr[i]);
    i+=1
return outList

print rmvAllDuplicate(arr, dataCountTable(arr)) 

面试官似乎对此答案印象不深。它让我一直在寻找更好的aprooach。我找不到一个。

如果有人可以帮助我改进我的解决方案或建议一个新的更好的解决方案,那就太好了!

谢谢!

7 个答案:

答案 0 :(得分:4)

我会使用collection.Counter(或者我自己实现一个):

from collections import Counter
input_list = [1,2,4,5,2,3,1]
# expected_output_list = {4,5,3}

# make Counter object for list elements
# and pick up to list only those values for which count is 1 
singles = {x for x, count in Counter(input_list).items() if count == 1}
# filter your list to get only elements that were not duplicates
result = [x for x in input_list if x in singles]

或者@falsetru指出,你可以:

result = [x for x, count in Counter(input_list).items() if count == 1]

但是你不能保证在这种情况下保留你的清单的顺序(h / t @DSM)

这具有线性时间复杂度。

答案 1 :(得分:2)

您可以使用列表解析在一行中执行此操作:

in_list = [1,2,4,5,2,3,1]
out_list = [num for num in in_list if in_list.count(num) == 1]
# result: [4,5,3]

答案 2 :(得分:2)

我猜你是否不允许使用内置函数,你也不允许使用stdlib类。否则,请务必使用m.wasowski's answer

但你可以自己做同样的事情吗?

当然,Counter只是一种幻想dict。您可以实现自己的Counter,或者只是明确地执行相同的工作:

input_list = [1,2,4,5,2,3,1]
counts = {}
for value in input_list:
    counts.setdefault(value, 0)
    counts[value] += 1

现在它和他的其他代码一样:

singles = {x for x, count in counts.items() if count == 1}
result = [x for x in input_list if x in singles]

这实际上与您在“哈希表方法”中所做的一样。但它更简洁,更易读,更具惯用性,并且通过一个小但非零的常数更快,所以它可能仍然给面试者留下更深刻的印象。 (当然,所有这些事情都更适用于m.wasowski的版本。)

答案 3 :(得分:2)

虽然你的哈希表实现可以更加简洁,可读和惯用,但速度有所提升,我怀疑这不是你的面试官所失望的。

更有可能的是,他推动你寻求更好的解决方案,希望你能提出一个论证,为什么你的解决方案实际上是最优的,而是你搜索了一段时间然后放弃了。

所以,这里有很多事情需要证明:

  1. 此问题的任何解决方案都必须是O(N)时间。
  2. 您的解决方案是(摊销,平均且几乎总是)O(N)时间。
  3. 解决方案时间复杂度的乘数是合理的。
  4. 此问题的任何解决方案是O(N)时间必须是O(M)空间(其中M是不同值的数量)。
  5. 您的解决方案是O(M)空间。
  6. 解决方案空间复杂度的乘数是合理的。
  7. 即使是简单的,你也不会在采访中提出一个真实严谨的证据。其中一些,你甚至可能无法做出令人信服的案例 - 但提出可能的例外并承认你挥手的地方可能就足够了。例如:

    • Python的dict(和set)具有O(N)最坏情况时间;这只是O(1)摊销的平均案例。你的数据有什么可能比O(1)更糟糕吗?可能不是,但是......如果这是某人想要DoS的服务器的一部分,他们可以发送他们想要的任何输入数据呢?
    • 他给你的所有价值都是小整数。这是否保证是真的?在这种情况下,请不要使用dict来计算您的计数,只需使用list(range(0, P)),其中P是最大数量。然后它是O(P)空间,听起来比O(M)差,除了乘数会小得多 - 列表大约占空间的1/3(只是值,而不是哈希,键和值),所以如果P << M/3这是一场胜利。它也可能是速度上的胜利,因为没有必要保持散列值。使用array.array可以做得更好。
    • Python哈希表对于存储具有较小计数的集合和字典来说是过度的。自定义哈希表是否可以显着减少或不足以值得呢?

答案 4 :(得分:0)

尝试:简单

l=[1,2,4,5,2,3,1]
[x for x in l if l.count(x)==1 ]

它将删除所有独特的项目

答案 5 :(得分:-1)

遍历列表并为列表中显示的特定元素添加标记。如果再次遇到相同的元素,则标记已经设置,您不想再将该元素添加到列表中。这将导致线性时间算法。猜猜这就是为什么面试官对你的解决方案不满意。 Hashing实际上也是如此,但是您正在为维护哈希表创建一个巨大的重载。

def f(seq): 
   seen = {}
   result = []
   for item in seq:
       if item in seen: continue
       seen[item] = 1
       result.append(item)
   return result

答案 6 :(得分:-1)

Python中的set是一个没有重复项的集合。您可以将列表删除并删除重复的项目,方法是将其转换为set,然后返回列表:

l = [1,2,3,2,4,3]
l = list(set(l))
print l
output: [1,2,3,4]