web-dev-qa-db-ja.com

Pythonリストでソートとuniqを行う最もクリーンな方法は何ですか?

Python list my_listを含む['foo', 'foo', 'bar']

niquify でリストをソートする最もPython的な方法は何ですか?
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()
55
knorv
my_list = sorted(set(my_list))
# 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]]
16
tzot

簡単なソリューションはIgnacioによって提供されます—sorted(set(foo))

一意のデータがある場合、sorted(set(...))を実行するだけでなく、常にセットを保存し、場合によっては並べ替えられたバージョンの値を引き出したいという合理的な可能性があります。 (その時点で、人々がよくデータベースを使用するようなもののように聞こえ始めます。)

ソートされたリストがあり、対数のメンバーシップをチェックし、最悪の線形時間で項目を追加する場合、 bisect module を使用できます。

常にこの状態を維持したい場合、物事を単純化したり、一部の操作のパフォーマンスを向上させたい場合は、 blist.sortedset

5
Mike Graham

他の人は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

これは、 itertools documentation の「pairwise」または「unique_justseen」レシピを使用してさらに簡略化できます。

2
taleinat