如何在列表中找到重复项而不创建单独的列表?

问题描述:

如何在列表中找到重复项而不创建任何其他列表?如何在列表中找到重复项而不创建单独的列表?

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

在结束

A = [1,4] 
+0

你说的是除去未受骗者还是什么? –

+0

如果原始列表中有三个'4',你想要结果有两个'4'还是一个? – Cyphase

+0

另外,您是否在意订单?结果可以是“[4,1]”吗? – Cyphase

所以,你想一个函数,它接受一个列表,以及该列表仅含有最初复制这些元素发生变异?我假设创建新列表的限制适用于任何新的集合。在提出有关算法的问题时,最好尽可能地明确要求。

这似乎是一个奇怪的要求,在这个算法中没有其他的收集,但它是可能的。 一个简单但低效的解决方案将是接近它是这样的:

  • 对于每个元件,x
    • 设置一个布尔标志的值,例如,hasDuplicatesfalse
    • 对的每个元素的权利xy
      • 如果yx,再重复移动它,并设置hasDuplicatestrue
    • 如果hasDuplicates是假的,除去x

如果没有创建另一个集合的限制可以放宽,或者如果算法的结果可能是一个新的列表,而不是旧的列表,你会发现更多(时间)有效的方式来做到这一点。

您可以使用set只得到唯一的值,然后将其删除,一个接一个,从原来的名单 - 因此,只有重复仍将:

a = [1,2,1,3,4,5,4] 
s = list(set(a)) 
for x in s: 
    a.remove(x) 
print a # [1, 4] 

另一种优雅的选项,我从Ritesh Kumar“偷”是:
收集只出现一次以上的项目,使用设置删除复本,并与list包装它返回一个列表的结果:

a = [1,2,1,3,4,5,4] 
print list(set([x for x in a if a.count(x) > 1])) # [1, 4] 

这应该做你需要什么,除非澄清:

def find_duplicated_items(data): 
    seen = set() 
    duplicated = set() 

    for x in data: 
     if x in seen: 
      duplicated.add(x) 
     else: 
      seen.add(x) 

    return duplicated 

这需要一个迭代并返回一组;你可以把它变成一个列表list(results)

UPDATE:

这里做,作为发电机的另一种方式。只是因为:)。

from collections import Counter 

def find_duplicated(iterable, atleast=2): 
    counter = Counter() 
    yielded = set() 

    for item in iterable: 
     counter[item] += 1 
     if (counter[item] >= atleast) and (item not in yielded): 
      yield item 
      yielded.add(item) 
+0

虽然这个问题只是说明没有创建新的'列表',但我会认为要求是没有任何新的收集。此外,它似乎需要一种方法,它改变现有的列表而不是创建一个新的列表。这是完全正确的解决方案,否则我认为! – Oly

+0

@ Oly'Oil'Sourbut - 您能否解释一下创建集合和创建不同列表的不同之处? – nname

+0

计算机科学中的@Nidhi A ['collection'](http://en.wikipedia.org/wiki/Collection_(abstract_data_type))指的是一些相关的数据结构。一个[列表](http://en.wikipedia.org/wiki/List_(abstract_data_type))是一种集合,表示一些有订单的项目,通常可以通过索引访问(例如'a'一个列表,我想'a [4]',第五个 - 从0 - 在'a'中计数)。根据我的经验,[set](http://en.wikipedia.org/wiki/Set_(abstract_data_type))是第二种最常见的集合 - 它存储的数据没有特定的顺序,也没有重复。 – Oly

我会去检查,每个元素,如果它出现在它之前,但不是之后。如果它不合适,那么它不是重复的,或者是您不想保留的副本的其他发生。两种情况我们都不保留。

def simplify(a_list): 
    for i in range(len(a_list) - 1, -1, -1): 
     value = a_list[i] 
     if not value in a_list[:i] or value in a_list[i+1:]: 
      del a_list[i] 

不确定使用切片是否符合您的要求。


用法:

>>> A = [1,2,1,3,4,5,4] 
>>> simplify(A) 
>>> A 
[1, 4] 
>>> A = [1,1,1,1,1,2,2,2,2] 
>>> simplify(A) 
>>> A 
[1, 2] 
>>> A = [1,1,1,1,1] 
>>> simplify(A) 
>>> A 
[1] 
>>> A = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
>>> simplify(A) 
>>> A 
[] 
+0

在python 2我相信'范围(...)'创建一个列表。 – Paul

+0

但是'xrange'没有。 –

此代码出现删除重复2次和非重复的地方,产生含有独特只重复旧的列表。我没有彻底测试它。请注意,所需时间将缩放为O(N ** 2),其中N是输入列表的长度。

与其他解决方案不同,这里没有构建新列表,甚至没有列出for循环或列表理解。

文件: “dup.py”

def dups(mylist): 
    idx = 0 
    while(idx<len(mylist)): 
     delidx = idx+1 
     ndeleted = 0 
     while delidx < len(mylist): 
      if mylist[delidx] == mylist[idx]: 
       del mylist[delidx] 
       ndeleted += 1 
      else: 
       delidx += 1 
     if ndeleted==0: 
      del mylist[idx] 
     else: 
      idx += 1 
    return mylist 

用法(IPython中)

In [1]: from dup import dups 

In [2]: dups([1,1,1,1,1]) 
Out[2]: [1] 

In [3]: dups([1,1,2,1,1]) 
Out[3]: [1] 

In [4]: dups([1,1,2,2,1]) 
Out[4]: [1, 2] 

In [5]: dups([1,1,2,1,2]) 
Out[5]: [1, 2] 

In [6]: dups([1,2,3,1,2]) 
Out[6]: [1, 2] 

In [7]: dups([1,2,1,3,4,5,4]) 
Out[7]: [1, 4]