2016-07-26 21 views
5

Ich möchte eine bestimmte Anzahl von Duplikaten einer Liste entfernen, ohne alle zu entfernen. Zum Beispiel habe ich eine Liste [1,2,3,4,4,4,4,4] und ich möchte 3 der 4 entfernen, so dass ich mit [1,2,3,4,4] verlassen werde. Eine naive Art und Weise ist es wahrscheinlichEinige Duplikate aus einer Liste in Python entfernen

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

Gibt es eine Möglichkeit, die drei 4 ist in einem Durchlauf durch die Liste zu tun zu tun wäre, zu entfernen, aber die beiden anderen halten.

+0

@ dot.Py: Definitiv kein Duplikat davon, weil wir nur versuchen, eine begrenzte Anzahl von Elementen aus der Liste zu entfernen und Duplikate nicht vollständig zu eliminieren. – user2357112

+2

Möchten Sie 'n' Duplikate entfernen? Oder behaupten, dass es höchstens "m" Duplikate eines gegebenen Gegenstandes gibt? – mgilson

+2

Ist es auch wichtig, welche Duplikate entfernt werden? (z. B. können Sie die _first_ 4 Dupes entfernen oder müssten es die letzten 4 sein?) – mgilson

Antwort

6

Wenn Sie nur die ersten n Vorkommen von etwas aus einer Liste entfernen mögen, ist dies recht einfach mit einem Generator zu tun:

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 

Verwendung wie folgt aussieht:

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

eines Keeping angegebene Anzahl von Duplikaten von beliebig Artikel ist ähnlich einfach, wenn wir ein wenig zusätzlichen Hilfsspeicher verwenden:

Die Verwendung ist ähnlich:

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] 

Hier ist der Eingang ist die Liste und die maximale Anzahl der Elemente, die Sie behalten möchten. Der Vorbehalt ist, dass die Artikel hashable sein müssen ...

-1

Ich kann es auf verschiedene Weise mit Sammlungen lösen.

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

Aber das entfernt _alle_ Duplikate und nutzt den "Counter" überhaupt nicht wirklich aus ... – mgilson

+0

Dies kann durch Verwendung des Wertes für den jeweiligen Schlüssel erreicht werden. Die cntLi.items() stellt eine Liste von Tupeln bereit, in denen die eindeutige Nummer im Schlüssel vorhanden ist und die Zählung der Zahl im Wert vorhanden ist. Indem Sie den Wert verarbeiten, können Sie die Operation festlegen. –

+0

Rechts. Es kann definitiv so gemacht werden (und das wäre nicht einmal eine schlechte Lösung), aber wie es ist, Sie beantworten diesen entscheidenden Schritt fehlt. – mgilson

0

können Sie Python-Set-Funktionalität verwenden, um mit dem & Bediener eine Liste von Listen zu erstellen und dann die Liste glätten. Die Ergebnisliste wird [1, 2, 3, 4, 4] sein.

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] 

Als eine Funktion würden Sie Folgendes haben.

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

Hier ist ein weiterer Trick, der manchmal nützlich sein könnte. Nicht als das empfohlene Rezept zu nehmen.

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

Wenn die Liste sortiert ist, gibt es die schnelle Lösung:

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:] 

Beachten Sie, dass dies das neue Array zurückgibt, so dass Sie arr = removeCount tun wollen (arr, 4, 3)

Verwandte Themen