Каков самый чистый способ сделать сортировку плюс uniq в списке Python?

Рассмотрим список Python my_list, содержащий ['foo', 'foo', 'bar'].

Каков самый питоновский способ uniquify и отсортировать список? (подумайте cat my_list | sort | uniq)

Вот как я это делаю сейчас, и пока он работает, я уверен, что есть лучшие способы сделать это.

my_list = []
...
my_list.append("foo")
my_list.append("foo")
my_list.append("bar")
...
my_list = set(my_list)
my_list = list(my_list)
my_list.sort()

Ответ 1

my_list = sorted(set(my_list))

Ответ 2

# Python ≥ 2.4
# because of (generator expression) and itertools.groupby, sorted

import itertools

def sort_uniq(sequence):
    return (x[0] for x in itertools.groupby(sorted(sequence)))

Быстрее

import itertools, operator
import sys

if sys.hexversion < 0x03000000:
    mapper= itertools.imap # 2.4 ≤ Python < 3
else:
    mapper= map # Python ≥ 3

def sort_uniq(sequence):
    return mapper(
        operator.itemgetter(0),
        itertools.groupby(sorted(sequence)))

Обе версии возвращают генератор, поэтому вы можете отправить результат в тип списка:

sequence= list(sort_uniq(sequence))

Обратите внимание, что это также будет работать с не-хэшируемыми элементами:

>>> list(sort_uniq([[0],[1],[0]]))
[[0], [1]]

Ответ 3

Прямое решение предоставляется Игнасио sorted(set(foo)).

Если у вас есть уникальные данные, есть разумный шанс, что вы просто не хотите делать sorted(set(...)), а скорее хранить набор все время и иногда вытаскивать отсортированную версию значений. (В этот момент он начинает звучать так, как будто люди часто используют базу данных тоже.)

Если у вас есть отсортированный список, и вы хотите проверить членство на логарифмическом и добавить элемент в наихудшем линейном времени, вы можете использовать модуль bisect.

Если вы хотите постоянно сохранять это условие и хотите упростить ситуацию или сделать некоторые операции более эффективными, вы можете рассмотреть blist.sortedset.

Ответ 4

Другие упомянули отсортированный (set (my_list)), который работает для хэшируемых значений, таких как строки, числа и кортежи, но не для нераспаковываемых типов, таких как списки.

Чтобы получить отсортированный список значений любого сортируемого типа без дубликатов:

from itertools import izip, islice
def unique_sorted(values):
    "Return a sorted list of the given values, without duplicates."
    values = sorted(values)
    if not values:
        return []
    consecutive_pairs = izip(values, islice(values, 1, len(values)))
    result = [a for (a, b) in consecutive_pairs if a != b]
    result.append(values[-1])
    return result

Это может быть дополнительно упрощено с помощью рецептов "попарно" или "unique_justseen" из документации itertools.

Ответ 5

Не могу сказать, что это чистый способ сделать это, но просто для удовольствия:

my_list = [x for x in sorted(my_list) if not x in locals()["_[1]"]]