Ostatnio zauważyłem, że kiedy jestem konwertowania list
do set
rzędu elementów ulega zmianie i jest klasyfikowane według charakteru.
Rozważmy ten przykład:
x=[1,2,20,6,210]
print x
# [1, 2, 20, 6, 210] # the order is same as initial order
set(x)
# set([1, 2, 20, 210, 6]) # in the set(x) output order is sorted
Moje pytania to -
- Dlaczego to się dzieje?
- Jak mogę wykonać operacje na zestawach (zwłaszcza na ustawieniach różnicy) bez utraty pierwotnego zamówienia?
unique = list(dict.fromkeys([1, 2, 1]).keys())
. To działa, ponieważdict
s zachowaj zamówienie reklamowe teraz.Odpowiedzi:
A
set
to nieuporządkowana struktura danych, więc nie zachowuje kolejności reklamowej.To zależy od twoich wymagań. Jeśli masz normalną listę i chcesz usunąć jakiś zestaw elementów, zachowując kolejność na liście, możesz to zrobić za pomocą zrozumienia listy:
Jeśli potrzebujesz struktury danych, która obsługuje zarówno szybkie testy członkostwa, jak i zachowanie kolejności wstawiania , możesz użyć kluczy ze słownika Pythona, który począwszy od Pythona 3.7 gwarantuje zachowanie kolejności wstawiania:
b
tak naprawdę nie trzeba tutaj zamawiać - możesz też użyćset
. Pamiętaj, żea.keys() - b.keys()
zwraca różnicę zestawu jako aset
, więc nie zachowa zamówienia reklamowego.W starszych wersjach Pythona możesz
collections.OrderedDict
zamiast tego użyć :źródło
None
jest językiem singleton z gwarancją. W CPythonie rzeczywisty koszt jest tylko wskaźnikiem (chociaż ten koszt jest zawsze obecny, ale w przypadku dyktowania można prawie rozważyć,None
a inne pojedyncze lub udostępniane odniesienia są „bezpłatne”), więc słowo maszynowe, prawdopodobnie 8 bajtów na nowoczesnych komputerach . Ale tak, to nie jest tak wydajne przestrzennie, jak mógłby być zestaw.dict.fromkeys([1, 2, 1]).keys()
ponieważ regularniedict
zachowujesz kolejność.W Pythonie 3.6jest inne rozwiązanie dla Pythona 2 i 3:set()
teraz powinno zachować kolejność, aleźródło
x.index
jest wywoływany, wykonywane jest wyszukiwanie liniowe. Jeśli nie masz nicset
przeciwko złożoności kwadratowej, nie ma powodu, aby używać w pierwszej kolejności.set()
nie jest uporządkowane w Pythonie 3.6, nawet jako szczegół implementacji, myślisz odict
sint
często sąx=[1,2,-1,20,6,210]
stworzyć zestaw. Zobaczysz, że nie jest w ogóle uporządkowany, przetestowany w Pythonie 3.6.Odpowiadając na pierwsze pytanie, zbiór to struktura danych zoptymalizowana pod kątem operacji na zbiorach. Podobnie jak zbiór matematyczny, nie wymusza ani nie utrzymuje określonej kolejności elementów. Abstrakcyjna koncepcja zestawu nie wymusza porządku, więc nie jest wymagana realizacja. Kiedy tworzysz zestaw z listy, Python ma swobodę zmiany kolejności elementów na potrzeby wewnętrznej implementacji, której używa dla zbioru, który jest w stanie efektywnie wykonywać operacje na zbiorach.
źródło
usuń duplikaty i zachowaj kolejność za pomocą poniższej funkcji
sprawdź ten link
źródło
W matematyce istnieją zbiory i zbiory uporządkowane (osety).
W Pythonie tylko zestawy są implementowane bezpośrednio. Możemy emulować osety zwykłymi klawiszami dyktowania ( 3.7+ ).
Dany
Kod
Próbny
Repliki są usuwane, kolejność wstawiania zostaje zachowana.
Operacje podobne do zestawów na klawiszach dyktowania.
Detale
Uwaga: nieuporządkowana konstrukcja nie wyklucza zamówionych elementów. Raczej nie gwarantuje się zachowania porządku. Przykład:
Z przyjemnością odkryjesz, że lista i zestaw wielozbiorowy (mset) to dwie bardziej fascynujące, matematyczne struktury danych:
Podsumowanie
* Multiset może być pośrednio emulowany za
collections.Counter()
pomocą dyktowanego odwzorowania wielokrotności (zliczeń).źródło
Jak wskazano w innych odpowiedziach, zbiory są strukturami danych (i pojęciami matematycznymi), które nie zachowują kolejności elementów -
Jednak korzystając z kombinacji zestawów i słowników, możliwe jest, że możesz osiągnąć to, co chcesz - spróbuj użyć tych fragmentów:
źródło
Opierając się na odpowiedzi Svena, odkryłem, że używam kolekcji.OrderedDict pomogło mi osiągnąć to, co chcesz, a także pozwoliło mi dodać więcej elementów do dyktu:
Jeśli chcesz dodać przedmioty, ale nadal traktować to jak zestaw, możesz po prostu zrobić:
I możesz wykonać operację taką jak z.keys () na dyktacie i pobrać zestaw:
źródło
list(z.keys())
aby uzyskać listę wyjściową.Implementacja powyższej koncepcji najwyższego wyniku, która sprowadza ją z powrotem do listy:
Przetestowano (krótko) na Pythonie 3.6 i Pythonie 2.7.
źródło
Jeśli masz niewielką liczbę elementów na dwóch początkowych listach, na których chcesz wykonać operację ustawiania różnicy, zamiast używać,
collections.OrderedDict
która komplikuje implementację i czyni ją mniej czytelną, możesz użyć:Jego złożoność czasowa nie jest zbyt dobra, ale jest schludna i łatwa do odczytania.
źródło
Ciekawe, że ludzie zawsze używają „problemu ze świata rzeczywistego”, aby żartować z definicji w naukach teoretycznych.
Jeśli zestaw ma porządek, najpierw musisz rozwiązać następujące problemy. Jeśli Twoja lista zawiera zduplikowane elementy, jaka powinna być kolejność, gdy zamienisz ją w zestaw? Jaka jest kolejność, jeśli połączymy dwa zestawy? Jaka jest kolejność, jeśli przecinamy dwa zbiory o różnej kolejności na tych samych elementach?
Dodatkowo set znacznie szybciej wyszukuje określony klucz, co jest bardzo dobre w działaniu na zestawach (dlatego potrzebny jest zestaw, ale nie lista).
Jeśli naprawdę zależy Ci na indeksie, zachowaj go jako listę. Jeśli nadal chcesz wykonywać operacje na elementach na wielu listach, najprostszym sposobem jest utworzenie słownika dla każdej listy z tymi samymi kluczami w zestawie wraz z wartością listy zawierającą cały indeks klucza z oryginalnej listy.
źródło
Oto prosty sposób na zrobienie tego:
źródło