Usuwanie i wyodrębnianie zduplikowanych elementów z listy (tablicy) w Pythonie

Biznes

W tej części opisano, jak wygenerować nową listę w Pythonie przez usunięcie lub wyodrębnienie z listy (tablicy) zduplikowanych elementów.

Opisano tu następujące szczegóły.

  • Usuń zduplikowane elementy i wygeneruj nowe zestawienia
    • Nie należy zachowywać porządku oryginalnej listy.:set()
    • Zachowuje kolejność zgodną z oryginalnym wykazem: dict.fromkeys(),sorted()
    • Tablica dwuwymiarowa (lista list)
  • Wyodrębnij zduplikowane elementy i wygeneruj nową listę
    • Nie należy zachowywać porządku oryginalnej listy.
    • Zachowuje kolejność zgodną z oryginalnym wykazem
    • Tablica dwuwymiarowa (lista list)

Tę samą koncepcję można zastosować do krotek zamiast list.

Zobacz poniższy artykuł, aby dowiedzieć się

  • Jeśli chcesz określić, czy lista lub krotka ma zduplikowane elementy
  • Jeśli chcesz wyodrębnić elementy, które są wspólne lub nie są wspólne dla wielu listingów, a nie dla pojedynczego listingu

Należy pamiętać, że listy mogą przechowywać różne typy danych i różnią się ściśle od tablic. Jeśli chcesz obsługiwać tablice w procesach, które wymagają wielkości pamięci i adresów pamięci lub numerycznego przetwarzania dużych danych, użyj tablicy (biblioteka standardowa) lub NumPy.

Usuń zduplikowane elementy i wygeneruj nowe zestawienia

Nie należy zachowywać porządku oryginalnej listy.: set()

Jeśli nie ma potrzeby zachowywania kolejności oryginalnej listy, należy użyć funkcji set(), która generuje zbiór typu set.

Typ set jest typem danych, który nie posiada zduplikowanych elementów. Gdy do funkcji set() zostanie przekazana lista lub inny typ danych, zduplikowane wartości są ignorowane i zwracany jest obiekt typu set, w którym elementami są tylko unikalne wartości.

Jeśli chcesz, aby była to tuple, użyj funkcji tuple().

l = [3, 3, 2, 1, 5, 1, 4, 2, 3]

print(set(l))
# {1, 2, 3, 4, 5}

print(list(set(l)))
# [1, 2, 3, 4, 5]

Oczywiście można również pozostawić typ set. Więcej informacji na temat typu set można znaleźć w poniższym artykule.

Zachowuje kolejność zgodną z oryginalnym wykazem: dict.fromkeys(),sorted()

Jeśli chcesz zachować kolejność oryginalnej listy, użyj metody klasy fromkeys() typu słownikowego lub wbudowanej funkcji sorted().

dict.fromkeys() tworzy nowy obiekt słownika, którego kluczami są listy, tuple itp. określone w argumentach. Jeśli drugi argument zostanie pominięty, wartością jest Brak.

Ponieważ klucze słownikowe nie mają zduplikowanych elementów, zduplikowane wartości są ignorowane, tak jak w set(). Ponadto obiekt słownika można przekazać jako argument do funkcji list(), aby otrzymać listę, której elementy są kluczami słownika.

print(dict.fromkeys(l))
# {3: None, 2: None, 1: None, 5: None, 4: None}

print(list(dict.fromkeys(l)))
# [3, 2, 1, 5, 4]

Od wersji Pythona 3.7 (CPython ma 3.6) jest zagwarantowane, że funkcja dict.fromkeys() zachowuje kolejność argumentów. Wcześniejsze wersje używały wbudowanej funkcji sorted() w następujący sposób.

Dla argumentu key metody sorted, która zwraca posortowaną listę elementów, określ metodę tuple list index().

index() jest metodą, która zwraca indeks wartości (numer elementu na liście), który może być podany jako klucz funkcji sorted() w celu posortowania listy w oparciu o kolejność oryginalnej listy. Argument klucz jest określany jako obiekt wywoływalny (callable), więc nie piszemy ().

print(sorted(set(l), key=l.index))
# [3, 2, 1, 5, 4]

Tablica dwuwymiarowa (lista list)

W przypadku tablic dwuwymiarowych (list list) zastosowanie metody set() lub dict.fromkeys() powoduje wystąpienie błędu typu TypeError.

l_2d = [[1, 1], [0, 1], [0, 1], [0, 0], [1, 0], [1, 1], [1, 1]]

# l_2d_unique = list(set(l_2d))
# TypeError: unhashable type: 'list'

# l_2d_unique_order = dict.fromkeys(l_2d)
# TypeError: unhashable type: 'list'

Dzieje się tak dlatego, że obiekty niehashowalne, takie jak listy, nie mogą być elementami typu set ani kluczami typu dict.

Zdefiniuj następujące funkcje Kolejność oryginalnej listy jest zachowana i działa dla list jednowymiarowych i krotek.

def get_unique_list(seq):
    seen = []
    return [x for x in seq if x not in seen and not seen.append(x)]

print(get_unique_list(l_2d))
# [[1, 1], [0, 1], [0, 0], [1, 0]]

print(get_unique_list(l))
# [3, 2, 1, 5, 4]

Stosowana jest notacja z rozumieniem listy.

W tym przypadku stosujemy następujące rozwiązania

  • Jeśli X w „X i Y” jest fałszywy w ocenie zwarcia operatora i, to Y nie jest oceniany (nie jest wykonywany).
  • Metoda append() zwraca wartość None.

Jeśli elementy oryginalnej listy seq nie istnieją w widzianym, to obliczane są wartości then i after.
wykonywany jest polecenie seen.append(x) i element jest dodawany do seen.
Ponieważ metoda append() zwraca None, a None jest False, not seen.append(x) zwraca wartość True.
Wyrażenie warunkowe w notacji list comprehension staje się PRAWDĄ i jest dodawane jako element do ostatecznie wygenerowanej listy.

Jeśli elementy oryginalnej listy seq są obecne w seen, to x nieobecne w seen jest Fałszywe, a wyrażenie warunkowe dla wyrażenia rozumiejącego listę jest Fałszywe.
Dlatego nie są one dodawane jako elementy do ostatecznie utworzonej listy.

Inną metodą jest ustawienie osi argumentów w funkcji NumPy np.unique(), choć wynik będzie posortowany.

Wyodrębnij zduplikowane elementy i wygeneruj nową listę

Nie należy zachowywać porządku oryginalnej listy.

Aby z oryginalnej listy wyodrębnić tylko zduplikowane elementy, należy użyć funkcji collections.Counter().
Zwraca kolekcje.Counter (podklasę słownika) z elementami jako kluczami i liczbą elementów jako wartościami.

import collections

l = [3, 3, 2, 1, 5, 1, 4, 2, 3]

print(collections.Counter(l))
# Counter({3: 3, 2: 2, 1: 2, 5: 1, 4: 1})

Ponieważ jest to podklasa słownika, do pobierania kluczy i wartości można użyć funkcji items(). Wystarczy wyodrębnić klucze, których liczba jest równa lub większa niż dwa.

print([k for k, v in collections.Counter(l).items() if v > 1])
# [3, 2, 1]

Zachowuje kolejność zgodną z oryginalnym wykazem

Jak pokazano w powyższym przykładzie, od wersji Pythona 3.7 klucze kolekcji.Counter zachowują kolejność oryginalnej listy i tak dalej.

We wcześniejszych wersjach wystarczy sortowanie za pomocą sorted(), podobnie jak usuwanie zduplikowanych elementów.

print(sorted([k for k, v in collections.Counter(l).items() if v > 1], key=l.index))
# [3, 2, 1]

Jeśli chcesz wyodrębnić duplikaty w takiej postaci, po prostu pozostaw elementy z oryginalnej listy o numerze dwa lub więcej. Zachowana zostanie również kolejność.

cc = collections.Counter(l)
print([x for x in l if cc[x] > 1])
# [3, 3, 2, 1, 1, 2, 3]

Tablica dwuwymiarowa (lista list)

W przypadku tablic dwuwymiarowych (list list) poniższe funkcje są możliwe do wykonania, odpowiednio, gdy kolejność oryginalnej listy nie jest zachowana i gdy jest zachowana. Działa to również w przypadku list jednowymiarowych i krotek.

l_2d = [[1, 1], [0, 1], [0, 1], [0, 0], [1, 0], [1, 1], [1, 1]]
def get_duplicate_list(seq):
    seen = []
    return [x for x in seq if not seen.append(x) and seen.count(x) == 2]

def get_duplicate_list_order(seq):
    seen = []
    return [x for x in seq if seq.count(x) > 1 and not seen.append(x) and seen.count(x) == 1]

print(get_duplicate_list(l_2d))
# [[0, 1], [1, 1]]

print(get_duplicate_list_order(l_2d))
# [[1, 1], [0, 1]]

print(get_duplicate_list(l))
# [3, 1, 2]

print(get_duplicate_list_order(l))
# [3, 2, 1]

Jeśli chcesz wyodrębnić duplikaty, pozostaw elementy z oryginalnej listy, których liczba wynosi co najmniej dwa.

print([x for x in l_2d if l_2d.count(x) > 1])
# [[1, 1], [0, 1], [0, 1], [1, 1], [1, 1]]

Zwróć uwagę, że ponieważ złożoność obliczeniowa funkcji count() wynosi O(n), pokazana powyżej funkcja, która wielokrotnie wykonuje count(), jest bardzo nieefektywna. Być może istnieje mądrzejszy sposób.

Counter jest podklasą słownika, więc jeśli do funkcji collections.Counter() przekażesz listę lub tuple, których elementy są listami lub innymi obiektami niehashowalnymi, wystąpi błąd i nie będziesz mógł z niej skorzystać.

# print(collections.Counter(l_2d))
# TypeError: unhashable type: 'list'