У цьому розділі описано, як створити новий список у Python шляхом видалення або вилучення повторюваних елементів зі списку (масиву).
Тут описано наступні деталі.
- Видаліть повторювані елементи та створіть нові списки
- Не зберігайте порядок вихідного списку:
set()
- Зберігає порядок вихідного списку:
dict.fromkeys()
,sorted()
- Двовимірний масив (список списків)
- Не зберігайте порядок вихідного списку:
- Витягніть повторювані елементи та створіть новий список
- Не зберігайте порядок вихідного списку
- Зберігає порядок вихідного списку
- Двовимірний масив (список списків)
Таку ж концепцію можна застосувати до кортежів замість списків.
Дивіться наступну статтю для
- Якщо ви хочете визначити, чи містить список або кортеж повторювані елементи
- Якщо ви хочете витягти елементи, які є загальними чи не спільними для кількох списків замість одного списку
Зауважте, що списки можуть зберігати різні типи даних і суворо відрізняються від масивів. Якщо ви хочете обробляти масиви в процесах, які вимагають розміру пам’яті та адрес пам’яті або чисельної обробки великих даних, використовуйте масив (стандартна бібліотека) або NumPy.
Видаліть повторювані елементи та створіть нові списки
Не зберігайте порядок вихідного списку:set()
Якщо немає необхідності зберігати порядок вихідного списку, використовуйте set(), який генерує набір типів набору.
Тип набору — це тип даних, який не має повторюваних елементів. Коли список або інший тип даних передається в set(), повторювані значення ігноруються, і повертається об’єкт типу set, в якому лише унікальні значення є елементами.
Якщо ви хочете зробити його кортежом, використовуйте 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]
Звичайно, його також можна залишити як налаштований. Перегляньте наступну статтю для отримання додаткової інформації про набір типу набору.
Зберігає порядок вихідного списку:dict.fromkeys(),sorted()
Якщо ви хочете зберегти порядок вихідного списку, скористайтеся методом класу fromkeys() типу словника або вбудованою функцією sorted().
dict.fromkeys() створює новий об’єкт словника, ключами якого є списки, кортежи тощо, зазначені в аргументах. Якщо другий аргумент опущено, значення дорівнює None.
Оскільки ключі словника не мають повторюваних елементів, повторювані значення ігноруються, як у set(). Крім того, об’єкт словника можна передати як аргумент у list(), щоб отримати список, елементами якого є ключі словника.
print(dict.fromkeys(l))
# {3: None, 2: None, 1: None, 5: None, 4: None}
print(list(dict.fromkeys(l)))
# [3, 2, 1, 5, 4]
З Python 3.7 (CPython — 3.6) гарантовано, що dict.fromkeys() зберігає порядок послідовності аргументів. Попередні версії використовували вбудовану функцію sorted() наступним чином.
Вкажіть метод кортежу списку index() для ключа аргументу sorted, який повертає відсортований список елементів.
index() — це метод, який повертає індекс значення (номер елемента в списку), який можна вказати як ключ sorted() для сортування списку на основі порядку вихідного списку. Ключ аргументу вказується як викликаний (викликаний) об’єкт, тому не пишіть ().
print(sorted(set(l), key=l.index))
# [3, 2, 1, 5, 4]
Двовимірний масив (список списків)
Для двовимірних масивів (списків списків) метод, що використовує set() або dict.fromkeys(), призводить до помилки типу.
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'
Це пов’язано з тим, що нехешовані об’єкти, такі як списки, не можуть бути елементами набору типів або ключами типу dict.
Визначте такі функції. Порядок вихідного списку зберігається і працює для одновимірних списків і кортежів.
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]
Використовується позначення розуміння списку.
- ПОВ’ЯЗАНІ:Як використовувати списки Python
Тут ми використовуємо наступне
- Якщо X в “X і Y” є хибним в оцінці короткого замикання оператора і, то Y не оцінюється (не виконується).
- Метод append() повертає None.
Якщо елементи вихідного списку seq не існують у побаченому, обчислюються then і after.
seen.append(x) виконується, і елемент додається до seen.
Оскільки метод append() повертає None, а None є False, not seen.append(x) має значення True.
Умовний вираз у нотації для розуміння списку стає True і додається як елемент остаточного створеного списку.
Якщо елементи вихідного списку seq присутні в seen, то x not in seen має значення False, а умовний вираз для виразу розуміння списку – False.
Тому вони не додаються як елементи остаточного створеного списку.
Іншим методом є встановлення осі аргументів у функції NumPy np.unique(), хоча результат буде відсортований.
Витягніть повторювані елементи та створіть новий список
Не зберігайте порядок вихідного списку
Щоб витягти лише повторювані елементи з вихідного списку, використовуйте collections.Counter().
Повертає collections.Counter (підклас словника) з елементами як ключами та кількістю елементів як значеннями.
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})
Оскільки це підклас словника, items() можна використовувати для отримання ключів і значень. Досить витягти ключі, число яких становить два або більше.
print([k for k, v in collections.Counter(l).items() if v > 1])
# [3, 2, 1]
Зберігає порядок вихідного списку
Як показано в прикладі вище, починаючи з Python 3.7, ключі collections.Counter зберігають порядок вихідного списку тощо.
У попередніх версіях достатньо сортування за допомогою sorted(), як і видалення повторюваних елементів.
print(sorted([k for k, v in collections.Counter(l).items() if v > 1], key=l.index))
# [3, 2, 1]
Якщо ви хочете витягти дублікати такими, як вони є, просто залиште елементи з вихідного списку з двома або більше. Порядок також збережено.
cc = collections.Counter(l)
print([x for x in l if cc[x] > 1])
# [3, 3, 2, 1, 1, 2, 3]
Двовимірний масив (список списків)
Для двовимірних масивів (списків списків) можливі такі функції, коли порядок вихідного списку не зберігається і коли він зберігається відповідно. Він також працює для одновимірних списків і кортежів.
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]
Якщо ви хочете витягти з дублікатами, залиште елементи з вихідного списку з кількістю два або більше.
print([x for x in l_2d if l_2d.count(x) > 1])
# [[1, 1], [0, 1], [0, 1], [1, 1], [1, 1]]
Зауважте, що, оскільки обчислювальна складність count() дорівнює O(n), показана вище функція, яка багаторазово виконує count(), дуже неефективна. Можливо, є більш розумний спосіб.
Лічильник є підкласом словника, тому якщо ви передасте в collections.Counter( список або кортеж, елементами якого є списки або інші об’єкти, які не можна хешувати), виникне помилка, і ви не зможете ним скористатися.
# print(collections.Counter(l_2d))
# TypeError: unhashable type: 'list'