Какой самый чистый способ сделать сортировку плюс uniq в списке Python? - PullRequest
54 голосов
/ 28 мая 2010

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

Какой самый Pythonic способ 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()

Ответы [ 5 ]

90 голосов
/ 28 мая 2010
my_list = sorted(set(my_list))
15 голосов
/ 29 мая 2010
# 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]]
5 голосов
/ 28 мая 2010

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

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

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

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

2 голосов
/ 29 мая 2010

Другие упомянули sorted (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

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

0 голосов
/ 28 мая 2010

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

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