2016-07-26 223 views
5

我想删除一定数量的列表重复项而不删除所有项。例如,我有一个列表[1,2,3,4,4,4,4,4],我想删除其中的3个,这样我就剩下了[1,2,3,4,4]。一个天真的方式做到这一点很可能是从Python列表中删除一些重复项

def remove_n_duplicates(remove_from, what, how_many): 
    for j in range(how_many): 
     remove_from.remove(what) 

有没有办法做到卸下三个4的在一次通过列表,但保留其他两个。

+0

@ dot.Py:绝对不是重复的,因为我们只是试图从列表中删除有限数量的项目,而不是完全消除重复项目。 – user2357112

+2

你想删除'n'重复?或者断言任何给定项目至多有“m”个副本? – mgilson

+2

另外,重要的是你删除了哪一个? (例如,你可以删除_first_4模糊,还是最后4个模板?) – mgilson

回答

6

如果你只是想从列表中删除第一n发生的事情,这是很容易做到与发电机:

def remove_n_dupes(remove_from, what, how_many): 
    count = 0 
    for item in remove_from: 
     if item == what and count < how_many: 
      count += 1 
     else: 
      yield item 

用法是这样的:

lst = [1,2,3,4,4,4,4,4] 
print list(remove_n_dupes(lst, 4, 3)) # [1, 2, 3, 4, 4] 

保持一个任何项目的指定重复项目是类似容易,如果我们使用一点额外的辅助存储:

from collections import Counter 
def keep_n_dupes(remove_from, how_many): 
    counts = Counter() 
    for item in remove_from: 
     counts[item] += 1 
     if counts[item] <= how_many: 
      yield item 

用法是相似的:

lst = [1,1,1,1,2,3,4,4,4,4,4] 
print list(keep_n_dupes(lst, 2)) # [1, 1, 2, 3, 4, 4] 

这里输入列表,并要保持项目的最大数量。需要注意的是,这些物品需要可排除...

-1

我可以用不同的方式使用集合来解决它。

from collections import Counter 
li = [1,2,3,4,4,4,4] 
cntLi = Counter(li) 
print cntLi.keys() 
+1

但是,这删除_all_重复,并没有真正利用“计数器”... – mgilson

+0

这可以通过使用各个键的值来实现。 cntLi.items()提供了一个元组列表,其中唯一的数字出现在键中,数字的数量出现在数值中。通过处理该值,您可以决定操作。 –

+0

没错。这绝对是可以这样做的(这甚至不是一个坏的解决方案),但事实上,你的回答缺少了这一关键步骤。 – mgilson

0

您可以使用Python集功能与&操作符来创建一个列表的列表,然后压平列表。结果列表将是[1,2,3,4,4]。

x = [1,2,3,4,4,4,4,4] 
x2 = [val for sublist in [[item]*max(1, x.count(item)-3) for item in set(x) & set(x)] for val in sublist] 

作为函数,您将拥有以下内容。

def remove_n_duplicates(remove_from, what, how_many): 
    return [val for sublist in [[item]*max(1, remove_from.count(item)-how_many) if item == what else [item]*remove_from.count(item) for item in set(remove_from) & set(remove_from)] for val in sublist] 
-1

这是另一个可能有用的技巧。不被视为推荐配方。

def remove_n_duplicates(remove_from, what, how_many): 
    exec('remove_from.remove(what);'*how_many) 
0

如果列表进行排序,有个快速的解决方案:

def remove_n_duplicates(remove_from, what, how_many): 
    index = 0 
    for i in range(len(remove_from)): 
     if remove_from[i] == what: 
      index = i 
      break 
    if index + how_many >= len(remove_from): 
     #There aren't enough things to remove. 
     return 
    for i in range(index, how_many): 
     if remove_from[i] != what: 
      #Again, there aren't enough things to remove 
      return 
    endIndex = index + how_many 
    return remove_from[:index+1] + remove_from[endIndex:] 

注意这返回新的数组,所以你想要做的ARR = removeCount(ARR,4,3)