2010-05-28 16 views
36

['foo', 'foo', 'bar'] içeren bir Python listesi my_list düşünün.Bir Python listesinde bir sıralama ve uniq yapmanın en temiz yolu nedir?

uniquify için en çok Pythonic yolu nedir ve bir listeyi sıralamak?
(düşün cat my_list | sort | uniq)

Şu anda bunu yapıyorum ve çalışırken de, bunu yapmanın daha iyi yolları olduğundan eminim.

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() 
+0

Olası dupl [Python listesinden çiftleri nasıl silebilir ve siparişi nasıl tutabiliriz?] (http://stackoverflow.com/questions/479897/how-to-remove-duplicates-from-python-list-and-keep-order) – sampablokuper

cevap

73
my_list = sorted(set(my_list)) 
+9

Not Bu sadece yıkanabilir tipler için çalışır, örneğin bu listelerde çalışmayacaktır. – taleinat

+0

Bunun, bellekte herşeyi yapması gerektiğine değinirken, 'sort' (genellikle?) Diskte kalmayı bilir. Bunu büyük miktarda bir veriye uygularsanız, 'MemoryError' üzerinde başarısız olmalıdır. İyi cevap olsa da :) –

+0

@ReutSharabani: Hayır, farklı olan 'sort()' yönteminin yerinde çalıştığı ve bu nedenle ek ayırma gerektirmediği. –

-4

bu o kadar temiz yoldur, ama sadece eğlence için diyemeyiz:

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

Bu çirkin, büyülü ve gereksiz kuadratik. –

+0

Elbette, not ettiğim gibi sadece eğlence için. – andreypopp

5

basit çözüm Ignacio- sorted(set(foo)) tarafından sağlanmaktadır.

Benzersiz verileriniz varsa, yalnızca sorted(set(...)) yapmak istemediğiniz, ancak her seferinde bir kümeyi saklamak ve zaman zaman değerlerin sıralı bir sürümünü çıkarmak için makul bir olasılık vardır. (Bu noktada, insanlar için de bir veritabanı sık sık kullanılan bir şey gibi geliyor.)

Sıralanmış bir listeniz varsa ve logaritmik üyeliği kontrol edip en kötü durumda doğrusal bir öğe eklemek istiyorsanız bisect module'u kullanabilirsiniz.

Bu durumu her zaman saklamak ve işleri basitleştirmek veya bazı işlemleri daha iyi gerçekleştirmek istiyorsanız, blist.sortedset'u düşünebilirsiniz.

+0

[Sortcontainers] 'ı düşünün (http://www.grantjenks.com/docs/sortedcontainers/). [SortedSet] (http://www.grantjenks.com/docs/sortedcontainers/sortedset.html) blist yerine. Bu [daha hızlı] (http://www.grantjenks.com/docs/sortedcontainers/performance.html) ve saf Python. – GrantJ

2

Diğerleri, dizeler, sayılar ve tuple gibi ayrılabilir değerler için çalışan, ancak listeler gibi paylaşılmaz türlerde olmayan, sıralanmış (set (my_list)) öğesinden bahsetmiştir.

yineleme olmadan, herhangi sıralanabilir türündeki değerler sıralanmış bir listesini almak için:

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 

Bu da itertools documentation gelen "çiftler halinde" veya "unique_justseen" tarifler kullanılarak basitleştirilebilir.

10
# 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))) 

hızlı:

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))) 

liste türüne sonucu tedarik etmek isteyebilirsiniz böylece iki sürüm, bir jeneratör dönmek:

bu olmayan çalışacağını
sequence= list(sort_uniq(sequence)) 

Not ayrıca yıkanabilir öğeler:

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

Eğer python3: Py3 haritası kullanıyorsanız ve Py2 itertools.imap içinde tam olarak aynı şeyi yapın. (Py3 iter'de (harita (...)) gereksizdir.) –

+0

Bu, büyük miktarda veriye sahip olduğunuz varsayılarak kabul edilen yanıttan çok daha iyidir. +1 –

+0

@ TheDemz, Python 3'ün o zamandan çok daha yaygın olduğunu dikkate alarak gerekli cevabı; Teşekkürler – tzot

İlgili konular