2016-07-26 222 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)