2017-02-22 1 views
3

Frage nur, wie sortieren Sie eine Liste nach Häufigkeit/Vorkommen in Python 2.7 und wenn 2 Elemente die gleiche Anzahl auftreten, dann ist das Element, das zuerst in der ursprünglichen Liste erscheint, vor dem anderen Element in der neuen Liste.python Wie sortieren Sie Listen nach Vorkommen, ohne Elemente aus der Liste zu entfernen?

Zum Beispiel:

list = [5,6,8,9,8,8,3,4,4,6,6] 
sorted_list = [6,6,6,8,8,8,4,4,5,9,3] 

Jede Idee, warum die Lösung nicht für funktioniert [1,3,3,3,2,2,2,1,1] .Die Ausgabe ist [3, 3,3,2,2,2,1,1,1] aber der korrekte Ausgang ist [1,1,1,3,3,3,2,2,2] Danke wieder

+2

ich nur eine Antwort geschrieben, aber ich frage mich, warum in Ihrer erwarteten Ausgabe der '8' ist vor der' 6 'obwohl' 6 'zuerst aufgetreten in dem ursprüngliche Liste? – MSeifert

+0

Sorry ich vermasselte die gewünschte Ausgabe Ich änderte es jetzt dank – jonny

+0

MSeiferts (& my) Code gibt die richtige Antwort für '[1,3,3,3,2,2,2,1,1]', und ich nehme an Mureiniks aktualisierte Version tut es auch, aber ich habe es nicht getestet. –

Antwort

2

Sie können verwenden die Counter Klasse von collections als Sortierschlüssel. Da Sie mehrere Elemente mit der gleichen Anzahl von Vorkommen haben, können Sie den Wert selbst als sekundären Sortierschlüssel verwenden, so dass identische Elemente zusammen gruppiert sind:

>>> from collections import Counter 
>>> lst = [5,6,8,9,8,8,3,4,4,6,6] 
>>> c = Counter(lst) 
>>> sorted(lst, key = lambda x : (c[x], x), reverse = True) 
[8, 8, 8, 6, 6, 6, 4, 4, 9, 5, 3] 

EDIT: Wie MSeifert kommentiert, sollen Bindungen gebrochen werden in der Reihenfolge der ersten Erscheinung, nicht der Wert des Elements. Dies kann mit der index Funktion auf der ursprünglichen Liste erfolgen:

>>> sorted(lst, key = lambda x : (-1 * c[x], lst.index(x))) 
[6, 6, 6, 8, 8, 8, 4, 4, 5, 9, 3] 
+0

sekundäre Sortierschlüssel hat immer einen besonderen Platz in meinem Herzen –

+0

das sagte, ich glaube, Sie vergessen zu definieren 'c' –

+0

@ Jean-FrançoisFabre yup - hatte ein paar Versuche, bis ich es richtig gemacht habe, und versuchte nur zu kopieren und einfügen die relevanten Zeilen. Offensichtlich habe ich eins vergessen :-) Editiert und behoben, danke fürs merken! – Mureinik

2

diese Art zu tun zu sortieren Sie die ersten Indizes und die Zählungen der einzelnen Elemente finden müssen. Ich werde eine Funktion verwenden, beides zu tun, aber es gibt auch andere Ansätze:

def count_and_first_index(it): 
    dct_counts = {} 
    dct_first = {} 
    for idx, item in enumerate(it): 
     if item in dct_counts: 
      dct_counts[item] += 1 
     else: 
      dct_counts[item] = 1 
      dct_first[item] = idx 

    return dct_counts, dct_first 

Dann einfache Sortierung ist mit einem key -Argument:

>>> lst = [5,6,8,9,8,8,3,4,4,6,6] 

>>> counts, firstidx = count_and_first_index(lst) 

>>> sorted(lst, key=lambda x: (counts[x], -firstidx[x]), reverse=True) 
[6, 6, 6, 8, 8, 8, 4, 4, 5, 9, 3] 

ich die index negiert, weil es umgekehrt sortiert und Sie wollte den ersten Gegenstand zuerst. Allerdings könnten Sie auch counts negieren und entfernen reverse:

>>> sorted(lst, key=lambda x: (-counts[x], firstidx[x])) 
[6, 6, 6, 8, 8, 8, 4, 4, 5, 9, 3] 
+1

Ich denke, Sie könnten auch 'sortierte (lst, Schlüssel = Lambda x: (- lst.count (x), lst.index (x)))' ', obwohl das ist ziemlich ineffizient in der Art, wie es das Zählen und Indizieren macht (O (n^2) anstelle von O (n)). –

+0

@ PM2Ring Ja, deshalb habe ich geschrieben: "Ich werde eine Funktion verwenden, um beides zu tun, aber es gibt auch andere Ansätze". Ich dachte, es würde mich daran hindern, einen 'O (n ** 2)' Ansatz zu verwenden (es durchläuft die Liste auch zweimal, weil 'count' und' index' getrennte Operationen sind!) Wenn ein 'O (n)' Ansatz ist (kurz und möglich. – MSeifert

+0

Nun, 2O (n²) ist immer noch O (n²) :) –

Verwandte Themen