it-swarm.com.de

Wie entfernen Sie Duplikate aus einer Liste, während Sie die Reihenfolge beibehalten?

Gibt es ein integriertes Programm, das Duplikate aus der Liste in Python entfernt und dabei die Reihenfolge beibehält? Ich weiß, dass ich mit einem Set Duplikate entfernen kann, aber dadurch wird die ursprüngliche Reihenfolge zerstört. Ich weiß auch, dass ich mich so rollen kann:

def uniq(input):
  output = []
  for x in input:
    if x not in output:
      output.append(x)
  return output

(Danke an Abwickeln für das Codebeispiel .)

Aber ich würde gerne eine eingebaute oder mehr Pythonic-Sprache verwenden, wenn möglich.

Zugehörige Frage: Was ist der schnellste Algorithmus in Python, um Duplikate aus einer Liste zu entfernen, sodass alle Elemente eindeutig sind und dabei die Reihenfolge beibehalten?

658
Josh Glover

Hier haben Sie einige Alternativen: http://www.peterbe.com/plog/uniqifiers-benchmark

Schnellster:

def f7(seq):
    seen = set()
    seen_add = seen.add
    return [x for x in seq if not (x in seen or seen_add(x))]

Warum sollten Sie seen.addseen_add zuweisen, anstatt nur seen.add aufzurufen? Python ist eine dynamische Sprache, und das Auflösen von seen.add bei jeder Iteration ist kostspieliger als das Auflösen einer lokalen Variablen. seen.add könnte sich zwischen den Iterationen geändert haben, und die Laufzeitumgebung ist nicht intelligent genug, um dies auszuschließen. Um auf Nummer sicher zu gehen, muss das Objekt jedes Mal überprüft werden.

Wenn Sie vorhaben, diese Funktion häufig für dasselbe Dataset zu verwenden, sind Sie mit einem bestellten Set vielleicht besser dran: http://code.activestate.com/recipes/528878/

O (1) Einfügen, Löschen und Member-Check pro Vorgang.

677
Markus Jarderot

Edit 2016

Wie Raymond darauf hingewiesen in Python 3.5+, wo OrderedDict in C implementiert ist, ist der Listenverständnisansatz langsamer als OrderedDict (es sei denn, Sie benötigen die Liste am Ende - und selbst dann nur, wenn die Eingabe sehr ist kurz). Die beste Lösung für 3.5+ ist also OrderedDict.

Wichtige Bearbeitung 2015

Als @abarnert notes enthält die more_itertools library (pip install more_itertools) eine unique_everseen - Funktion, mit der dieses Problem ohne unlesbare (not seen.add) mutations in gelöst werden kann Auflisten von Verständnis. Dies ist auch die schnellste Lösung:

>>> from  more_itertools import unique_everseen
>>> items = [1, 2, 0, 1, 3, 2]
>>> list(unique_everseen(items))
[1, 2, 0, 3]

Nur ein einfacher Bibliotheksimport und keine Hacks. Dies kommt von einer Implementierung des itertools-Rezepts unique_everseen , die wie folgt aussieht:

def unique_everseen(iterable, key=None):
    "List unique elements, preserving order. Remember all elements ever seen."
    # unique_everseen('AAAABBBCCDAABBB') --> A B C D
    # unique_everseen('ABBCcAD', str.lower) --> A B C D
    seen = set()
    seen_add = seen.add
    if key is None:
        for element in filterfalse(seen.__contains__, iterable):
            seen_add(element)
            yield element
    else:
        for element in iterable:
            k = key(element)
            if k not in seen:
                seen_add(k)
                yield element

In Python 2.7+ der allgemeiner Ausdruck (was funktioniert, aber nicht auf Geschwindigkeit optimiert ist, würde ich jetzt unique_everseen verwenden), um diese zu verwenden collections.OrderedDict :

Laufzeit: O(N)

>>> from collections import OrderedDict
>>> items = [1, 2, 0, 1, 3, 2]
>>> list(OrderedDict.fromkeys(items))
[1, 2, 0, 3]

Das sieht viel schöner aus als:

seen = set()
[x for x in seq if x not in seen and not seen.add(x)]

und verwendet nicht den hässlichen Hack:

not seen.add(x)

dies beruht auf der Tatsache, dass set.add eine In-Place-Methode ist, die immer None zurückgibt, sodass not None zu True ausgewertet wird.

Beachten Sie jedoch, dass die Hack-Lösung schneller ist, obwohl sie die Laufzeitkomplexität O (N) aufweist.

310
jamylak

In Python 2.7 besteht die neue Methode zum Entfernen von Duplikaten aus einer Iteration, während sie in der ursprünglichen Reihenfolge bleibt:

>>> from collections import OrderedDict
>>> list(OrderedDict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']

In Python 3.5 hat OrderedDict eine C-Implementierung. Meine Timings zeigen, dass dies für Python 3.5 nun sowohl der schnellste als auch der kürzeste Ansatz ist.

In Python 3.6 wurde das reguläre Diktat geordnet und kompakt. (Diese Funktion gilt für CPython und PyPy, ist jedoch in anderen Implementierungen möglicherweise nicht vorhanden.) Das gibt uns eine neue, schnellste Art, Deduktion durchzuführen, während die Ordnung erhalten bleibt:

>>> list(dict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']

In Python 3.7 ist der reguläre Befehl für beide Implementierungen garantiert. Die kürzeste und schnellste Lösung ist also:

>>> list(dict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']

Antwort auf @max: Wenn Sie zu 3.6 oder 3.7 wechseln und anstelle von OrderedDict das reguläre Diktat verwenden, können Sie die Performance auf keine andere Weise schlagen. Das Wörterbuch ist dicht und kann ohne großen Aufwand in eine Liste umgewandelt werden. Die Zielliste ist auf len (d) vorab festgelegt, wodurch alle Größenänderungen gespeichert werden, die bei einem Listenverständnis auftreten. Da die interne Schlüsselliste dicht ist, ist das Kopieren der Zeiger als eine Listenkopie fast schnell.

72
sequence = ['1', '2', '3', '3', '6', '4', '5', '6']
unique = []
[unique.append(item) for item in sequence if item not in unique]

einzigartig → ['1', '2', '3', '6', '4', '5']

38
dansalmo
from itertools import groupby
[ key for key,_ in groupby(sortedList)]

Die Liste muss nicht einmal sortiert sein, die Bedingung ist, dass gleiche Werte gruppiert werden.

Edit: Ich habe angenommen, dass "Erhaltung der Reihenfolge" impliziert, dass die Liste tatsächlich geordnet ist. Ist dies nicht der Fall, ist die Lösung von MizardX die richtige.

Community edit: Dies ist jedoch der eleganteste Weg, "doppelte aufeinanderfolgende Elemente in ein einzelnes Element zu komprimieren".

22
Rafał Dowgird

Ich denke, wenn Sie die Reihenfolge beibehalten wollen,

sie können dies versuchen:

list1 = ['b','c','d','b','c','a','a']    
list2 = list(set(list1))    
list2.sort(key=list1.index)    
print list2

ODER Sie können dies auch tun:

list1 = ['b','c','d','b','c','a','a']  
list2 = sorted(set(list1),key=list1.index)  
print list2 

Sie können dies auch tun:

list1 = ['b','c','d','b','c','a','a']    
list2 = []    
for i in list1:    
    if not i in list2:  
        list2.append(i)`    
print list2

Es kann auch so geschrieben werden:

list1 = ['b','c','d','b','c','a','a']    
list2 = []    
[list2.append(i) for i in list1 if not i in list2]    
print list2 
19
shamrock

Um kein totes Pferd zu treten (diese Frage ist sehr alt und hat bereits viele gute Antworten), aber hier ist eine Lösung mit Pandas, die unter vielen Umständen recht schnell ist und einfach zu bedienen ist. 

import pandas as pd

my_list = [0, 1, 2, 3, 4, 1, 2, 3, 5]

>>> pd.Series(my_list).drop_duplicates().tolist()
# Output:
# [0, 1, 2, 3, 4, 5]
15
Alexander

Für eine weitere sehr späte Antwort auf eine andere sehr alte Frage:

Die itertools -Rezepte haben eine Funktion, die dies mit der seen-Set-Technik ausführt, jedoch:

  • Verarbeitet eine Standardfunktion key.
  • Verwendet keine unanständigen Hacks.
  • Optimiert die Schleife, indem seen.add vorab gebunden wird, anstatt N-mal nachzuschlagen. (f7 tut dies auch, aber einige Versionen nicht.)
  • Optimiert die Schleife mithilfe von ifilterfalse, sodass Sie nur die eindeutigen Elemente in Python und nicht alle Elemente durchlaufen müssen. (Sie durchlaufen natürlich immer noch alle in ifilterfalse, aber das ist in C und viel schneller.)

Ist es tatsächlich schneller als f7? Das hängt von Ihren Daten ab, daher müssen Sie sie testen und sehen. Wenn Sie am Ende eine Liste wünschen, verwendet f7 einen Listcomp. Dies ist hier nicht möglich. (Sie können append anstelle von yielding direkt verwenden, oder Sie können den Generator in die list - Funktion einspeisen, aber keiner kann so schnell sein wie LIST_APPEND in einem Listcomp Normalerweise ist es nicht so wichtig, ein paar Mikrosekunden herauszudrücken, als eine leicht verständliche, wiederverwendbare, bereits geschriebene Funktion zu haben, für die nicht DSU erforderlich ist, wenn Sie dekorieren möchten.

Wie bei allen Rezepten ist es auch in more-iterools verfügbar.

Wenn Sie nur den Nein -key-Fall wünschen, können Sie ihn wie folgt vereinfachen:

def unique(iterable):
    seen = set()
    seen_add = seen.add
    for element in itertools.ifilterfalse(seen.__contains__, iterable):
        seen_add(element)
        yield element
11
abarnert

Fügen Sie einfach eine weitere (sehr performante) Implementierung einer solchen Funktionalität aus einem externen Modul hinzu1: iteration_utilities.unique_everseen :

>>> from iteration_utilities import unique_everseen
>>> lst = [1,1,1,2,3,2,2,2,1,3,4]

>>> list(unique_everseen(lst))
[1, 2, 3, 4]

Timings

Ich habe einige Timings gemacht (Python 3.6) und diese zeigen, dass es schneller als alle anderen getesteten Alternativen ist, einschließlich OrderedDict.fromkeys, f7 und more_itertools.unique_everseen:

%matplotlib notebook

from iteration_utilities import unique_everseen
from collections import OrderedDict
from more_itertools import unique_everseen as mi_unique_everseen

def f7(seq):
    seen = set()
    seen_add = seen.add
    return [x for x in seq if not (x in seen or seen_add(x))]

def iteration_utilities_unique_everseen(seq):
    return list(unique_everseen(seq))

def more_itertools_unique_everseen(seq):
    return list(mi_unique_everseen(seq))

def odict(seq):
    return list(OrderedDict.fromkeys(seq))

from simple_benchmark import benchmark

b = benchmark([f7, iteration_utilities_unique_everseen, more_itertools_unique_everseen, odict],
              {2**i: list(range(2**i)) for i in range(1, 20)},
              'list size (no duplicates)')
b.plot()

 enter image description here

Und um sicherzugehen, dass ich auch einen Test mit mehr Duplikaten durchgeführt habe, nur um zu sehen, ob es einen Unterschied macht:

import random

b = benchmark([f7, iteration_utilities_unique_everseen, more_itertools_unique_everseen, odict],
              {2**i: [random.randint(0, 2**(i-1)) for _ in range(2**i)] for i in range(1, 20)},
              'list size (lots of duplicates)')
b.plot()

 enter image description here

Und einer, der nur einen Wert enthält:

b = benchmark([f7, iteration_utilities_unique_everseen, more_itertools_unique_everseen, odict],
              {2**i: [1]*(2**i) for i in range(1, 20)},
              'list size (only duplicates)')
b.plot()

 enter image description here

In allen diesen Fällen ist die iteration_utilities.unique_everseen-Funktion am schnellsten (auf meinem Computer).


Diese iteration_utilities.unique_everseen-Funktion kann auch unhashable Werte in der Eingabe verarbeiten (jedoch mit O(n*n)-Leistung anstelle von O(n)-Leistung, wenn die Werte hashierbar sind).

>>> lst = [{1}, {1}, {2}, {1}, {3}]

>>> list(unique_everseen(lst))
[{1}, {2}, {3}]

1 Haftungsausschluss: Ich bin der Autor dieses Pakets.

10
MSeifert

Für keine hashbaren Typen (z. B. Liste von Listen), basierend auf MizardX:

def f7_noHash(seq)
    seen = set()
    return [ x for x in seq if str( x ) not in seen and not seen.add( str( x ) )]
6
zmk

In Python 3.7 und höher sind Wörterbücher garantiert , um ihre Reihenfolge beim Einfügen von Schlüsseln zu speichern. Die Antwort auf die Frage this fasst die aktuelle Situation zusammen.

Die OrderedDict-Lösung ist damit veraltet und ohne Importanweisungen können wir einfach Folgendes ausgeben:

>>> lst = [1, 2, 1, 3, 3, 2, 4]
>>> list(dict.fromkeys(lst))
[1, 2, 3, 4]
5
timgeb

5 x schneller reduzieren Variante aber raffinierter

>>> l = [5, 6, 6, 1, 1, 2, 2, 3, 4]
>>> reduce(lambda r, v: v in r[1] and r or (r[0].append(v) or r[1].add(v)) or r, l, ([], set()))[0]
[5, 6, 1, 2, 3, 4]

Erläuterung:

default = (list(), set())
# use list to keep order
# use set to make lookup faster

def reducer(result, item):
    if item not in result[1]:
        result[0].append(item)
        result[1].add(item)
    return result

>>> reduce(reducer, l, default)[0]
[5, 6, 1, 2, 3, 4]
3

Die rekursive Idee, die zur Definition der Haskell-Funktion nub für Listen verwendet wird, wäre ein rekursiver Ansatz:

def unique(lst):
    return [] if lst==[] else [lst[0]] + unique(filter(lambda x: x!= lst[0], lst[1:]))

z.B.:

In [118]: unique([1,5,1,1,4,3,4])
Out[118]: [1, 5, 4, 3]

Ich habe es für wachsende Datengrößen ausprobiert und eine sublineare Zeitkomplexität festgestellt (nicht endgültig, schlägt jedoch vor, dass dies für normale Daten in Ordnung ist).

In [122]: %timeit unique(np.random.randint(5, size=(1)))
10000 loops, best of 3: 25.3 us per loop

In [123]: %timeit unique(np.random.randint(5, size=(10)))
10000 loops, best of 3: 42.9 us per loop

In [124]: %timeit unique(np.random.randint(5, size=(100)))
10000 loops, best of 3: 132 us per loop

In [125]: %timeit unique(np.random.randint(5, size=(1000)))
1000 loops, best of 3: 1.05 ms per loop

In [126]: %timeit unique(np.random.randint(5, size=(10000)))
100 loops, best of 3: 11 ms per loop

Ich finde es auch interessant, dass dies durch andere Operationen leicht zur Eindeutigkeit verallgemeinert werden kann. So was:

import operator
def unique(lst, cmp_op=operator.ne):
    return [] if lst==[] else [lst[0]] + unique(filter(lambda x: cmp_op(x, lst[0]), lst[1:]), cmp_op)

Zum Beispiel könnten Sie eine Funktion übergeben, die den Begriff der Rundung auf dieselbe Ganzzahl verwendet, als wäre sie aus Gründen der Eindeutigkeit "Gleichheit":

def test_round(x,y):
    return round(x) != round(y)

dann würde unique (some_list, test_round) die eindeutigen Elemente der Liste bereitstellen, bei denen Eindeutigkeit nicht mehr traditionelle Gleichheit bedeutete (was durch die Verwendung einer Art von satzbasiertem oder auf Diktierschlüssel basierenden Ansatz für dieses Problem impliziert wird), sondern stattdessen beabsichtigte nur das erste Element, das für jede mögliche ganze Zahl K, auf die die Elemente gerundet werden könnten, auf K gerundet wird, z.

In [6]: unique([1.2, 5, 1.9, 1.1, 4.2, 3, 4.8], test_round)
Out[6]: [1.2, 5, 1.9, 4.2, 3]
3
ely

Die Antwort von MizardX bietet eine gute Sammlung verschiedener Ansätze.

Dies ist, was ich beim lauten Nachdenken kam:

mylist = [x for i,x in enumerate(mylist) if x not in mylist[i+1:]]
2
Saurabh Hirani

Sie können auf ein Listenverständnis verweisen, da es mit dem Symbol '_ [1]' erstellt wird. 
Die folgende Funktion ist beispielsweise eindeutig, wenn sie eine Liste von Elementen enthält, ohne ihre Reihenfolge zu ändern, indem auf ihr Listenverständnis Bezug genommen wird.

def unique(my_list): 
    return [x for x in my_list if x not in locals()['_[1]']]

Demo:

l1 = [1, 2, 3, 4, 1, 2, 3, 4, 5]
l2 = [x for x in l1 if x not in locals()['_[1]']]
print l2

Ausgabe:

[1, 2, 3, 4, 5]
2
Zhifeng Hu

Sie könnten eine Art hässlicher List-Verständnis-Hack machen.

[l[i] for i in range(len(l)) if l.index(l[i]) == i]
1
user1969453

Relativ effektiver Ansatz mit _sorted_ a numpy Arrays:

b = np.array([1,3,3, 8, 12, 12,12])    
numpy.hstack([b[0], [x[0] for x in Zip(b[1:], b[:-1]) if x[0]!=x[1]]])

Ausgänge:

array([ 1,  3,  8, 12])
1
dominecf

Eine einfache rekursive Lösung:

def uniquefy_list(a):
    return uniquefy_list(a[1:]) if a[0] in a[1:] else [a[0]]+uniquefy_list(a[1:]) if len(a)>1 else [a[0]]
1
Ilya Prokin
l = [1,2,2,3,3,...]
n = []
n.extend(ele for ele in l if ele not in set(n))

Ein Generatorausdruck, der die Suche nach O(1) einer Menge verwendet, um zu bestimmen, ob ein Element in die neue Liste aufgenommen werden soll.

1
kylie.a

Wenn Sie pandas routinemäßig verwenden und Ästhetik der Leistung vorgezogen wird, sollten Sie die integrierte Funktion pandas.Series.drop_duplicates beachten:

    import pandas as pd
    import numpy as np

    uniquifier = lambda alist: pd.Series(alist).drop_duplicates().tolist()

    # from the chosen answer 
    def f7(seq):
        seen = set()
        seen_add = seen.add
        return [ x for x in seq if not (x in seen or seen_add(x))]

    alist = np.random.randint(low=0, high=1000, size=10000).tolist()

    print uniquifier(alist) == f7(alist)  # True

Zeitliche Koordinierung: 

    In [104]: %timeit f7(alist)
    1000 loops, best of 3: 1.3 ms per loop
    In [110]: %timeit uniquifier(alist)
    100 loops, best of 3: 4.39 ms per loop
0
Lei

Eine Lösung ohne importierte Module oder Sets:

text = "ask not what your country can do for you ask what you can do for your country"
sentence = text.split(" ")
noduplicates = [(sentence[i]) for i in range (0,len(sentence)) if sentence[i] not in sentence[:i]]
print(noduplicates)

Gibt Ausgabe aus:

['ask', 'not', 'what', 'your', 'country', 'can', 'do', 'for', 'you']
0
Rob Murray

Wenn Sie einen Liner benötigen, könnte dies vielleicht helfen:

reduce(lambda x, y: x + y if y[0] not in x else x, map(lambda x: [x],lst))

... sollte funktionieren, aber korrigiere mich, wenn ich falsch liege

0
code22

Eliminieren Sie die doppelten Werte in einer Sequenz, aber behalten Sie die Reihenfolge der verbleibenden Elemente bei. Verwendung der Generatorfunktion für allgemeine Zwecke.

# for hashable sequence
def remove_duplicates(items):
    seen = set()
    for item in items:
        if item not in seen:
            yield item
            seen.add(item)

a = [1, 5, 2, 1, 9, 1, 5, 10]
list(remove_duplicates(a))
# [1, 5, 2, 9, 10]



# for unhashable sequence
def remove_duplicates(items, key=None):
    seen = set()
    for item in items:
        val = item if key is None else key(item)
        if val not in seen:
            yield item
            seen.add(val)

a = [ {'x': 1, 'y': 2}, {'x': 1, 'y': 3}, {'x': 1, 'y': 2}, {'x': 2, 'y': 4}]
list(remove_duplicates(a, key=lambda d: (d['x'],d['y'])))
# [{'x': 1, 'y': 2}, {'x': 1, 'y': 3}, {'x': 2, 'y': 4}]
0
Srivastava

dadurch wird die Reihenfolge beibehalten und in der Zeit O(n) ausgeführt. Grundsätzlich besteht die Idee darin, überall dort, wo ein Duplikat gefunden wurde, ein Loch zu erstellen und es auf den Boden zu sinken. verwendet einen Lese- und Schreibzeiger. Wenn ein Duplikat gefunden wird, rückt nur der Lesezeiger vor, und der Schreibzeiger bleibt auf dem doppelten Eintrag, um ihn zu überschreiben.

def deduplicate(l):
    count = {}
    (read,write) = (0,0)
    while read < len(l):
        if l[read] in count:
            read += 1
            continue
        count[l[read]] = True
        l[write] = l[read]
        read += 1
        write += 1
    return l[0:write]
0
Soham Joshi

der Ansatz von zmk verwendet ein Listenverständnis, das sehr schnell ist und dennoch die Reihenfolge auf natürliche Weise beibehält. Zum Anwenden auf Zeichenfolgen, bei denen zwischen Groß- und Kleinschreibung unterschieden wird, kann sie leicht geändert werden. Dadurch bleibt auch das Originalgehäuse erhalten.

def DelDupes(aseq) :
    seen = set()
    return [x for x in aseq if (x.lower() not in seen) and (not seen.add(x.lower()))]

Eng damit verbundene Funktionen sind:

def HasDupes(aseq) :
    s = set()
    return any(((x.lower() in s) or s.add(x.lower())) for x in aseq)

def GetDupes(aseq) :
    s = set()
    return set(x for x in aseq if ((x.lower() in s) or s.add(x.lower())))
0
Hewey Dewey

Eine In-Place-Methode

Diese Methode ist quadratisch, da wir für jedes Element der Liste eine lineare Suche in der Liste durchführen (dazu müssen wir die Kosten für das Neuanordnen der Liste wegen der dels addieren).

Das heißt, es ist möglich, an Ort und Stelle zu arbeiten, wenn wir am Ende der Liste beginnen und auf den Ursprung zugehen und jeden Begriff entfernen, der in der Unterliste links von ihm vorhanden ist

Diese Idee im Code ist einfach

for i in range(len(l)-1,0,-1): 
    if l[i] in l[:i]: del l[i] 

Ein einfacher Test der Implementierung

In [91]: from random import randint, seed                                                                                            
In [92]: seed('20080808') ; l = [randint(1,6) for _ in range(12)] # Beijing Olympics                                                                 
In [93]: for i in range(len(l)-1,0,-1): 
    ...:     print(l) 
    ...:     print(i, l[i], l[:i], end='') 
    ...:     if l[i] in l[:i]: 
    ...:          print( ': remove', l[i]) 
    ...:          del l[i] 
    ...:     else: 
    ...:          print() 
    ...: print(l)
[6, 5, 1, 4, 6, 1, 6, 2, 2, 4, 5, 2]
11 2 [6, 5, 1, 4, 6, 1, 6, 2, 2, 4, 5]: remove 2
[6, 5, 1, 4, 6, 1, 6, 2, 2, 4, 5]
10 5 [6, 5, 1, 4, 6, 1, 6, 2, 2, 4]: remove 5
[6, 5, 1, 4, 6, 1, 6, 2, 2, 4]
9 4 [6, 5, 1, 4, 6, 1, 6, 2, 2]: remove 4
[6, 5, 1, 4, 6, 1, 6, 2, 2]
8 2 [6, 5, 1, 4, 6, 1, 6, 2]: remove 2
[6, 5, 1, 4, 6, 1, 6, 2]
7 2 [6, 5, 1, 4, 6, 1, 6]
[6, 5, 1, 4, 6, 1, 6, 2]
6 6 [6, 5, 1, 4, 6, 1]: remove 6
[6, 5, 1, 4, 6, 1, 2]
5 1 [6, 5, 1, 4, 6]: remove 1
[6, 5, 1, 4, 6, 2]
4 6 [6, 5, 1, 4]: remove 6
[6, 5, 1, 4, 2]
3 4 [6, 5, 1]
[6, 5, 1, 4, 2]
2 1 [6, 5]
[6, 5, 1, 4, 2]
1 5 [6]
[6, 5, 1, 4, 2]

In [94]:                                                                                                                             
0
gboffi