bagaimana dengan yang sebaliknya, sekantong barang? (unordered and non-unique)
wim
19
@ wim collections.Counteradalah tas Python.
flornquake
1
Bagaimana jika sesuatu ditambahkan dua kali? Bagaimana seharusnya posisi itu?
McKay
2
@McKay - jika ingin mengikuti perilaku koleksi. OrderDict masih akan berada di posisi penambahan awal
wojtow
Jawaban:
206
Ada resep yang diatur (mungkin tautan baru ) resep untuk ini yang dirujuk dari Dokumentasi Python 2 . Ini berjalan pada Py2.6 atau lebih baru dan 3.0 atau lebih baru tanpa modifikasi apa pun. Antarmuka hampir persis sama dengan set normal, kecuali bahwa inisialisasi harus dilakukan dengan daftar.
OrderedSet([1,2,3])
Ini adalah MutableSet, jadi tanda tangan untuk .uniontidak cocok dengan yang ditetapkan, tetapi karena menyertakan __or__sesuatu yang serupa dapat dengan mudah ditambahkan:
@staticmethoddef union(*sets):
union =OrderedSet()
union.union(*sets)return union
def union(self,*sets):for set in sets:
self |= set
Saya cukup yakin Anda tidak diizinkan memiliki dua metode yang disebut uniondalam kelas yang sama. Yang terakhir akan "menang" dan yang pertama akan gagal ada saat runtime. Ini karena OrderedSet.union(tanpa parens) harus merujuk ke satu objek.
Kevin
3
Ada juga paket "orderedset" yang didasarkan pada resep yang sama tetapi diimplementasikan dalam Cython - pypi.python.org/pypi/orderedset .
mbdevpl
149
Set yang dipesan secara fungsional merupakan kasus khusus dari kamus yang diurutkan.
Kunci-kunci kamus itu unik. Jadi, jika seseorang mengabaikan nilai-nilai dalam kamus yang diurutkan (misalnya dengan menetapkannya None), maka pada dasarnya ia memiliki kumpulan yang diurutkan.
Pada Python 3.1 ada collections.OrderedDict. Berikut ini adalah contoh implementasi dari OrderedSet. (Perhatikan bahwa hanya beberapa metode yang perlu didefinisikan atau diganti: collections.OrderedDictdan collections.MutableSetlakukan pengangkatan berat.)
import collections
classOrderedSet(collections.OrderedDict, collections.MutableSet):def update(self,*args,**kwargs):if kwargs:raiseTypeError("update() takes no keyword arguments")for s in args:for e in s:
self.add(e)def add(self, elem):
self[elem]=Nonedef discard(self, elem):
self.pop(elem,None)def __le__(self, other):return all(e in other for e in self)def __lt__(self, other):return self <= other and self != other
def __ge__(self, other):return all(e in self for e in other)def __gt__(self, other):return self >= other and self != other
def __repr__(self):return'OrderedSet([%s])'%(', '.join(map(repr, self.keys())))def __str__(self):return'{%s}'%(', '.join(map(repr, self.keys())))
difference = __sub__
difference_update = __isub__
intersection = __and__
intersection_update = __iand__
issubset = __le__
issuperset = __ge__
symmetric_difference = __xor__
symmetric_difference_update = __ixor__
union = __or__
@Casebash: ya, satu mungkin ingin mendefinisikan kelas OrderedSetyang subclass OrderedDictdan abc.Setkemudian menentukan __len__, __iter__dan __contains__.
Stephan202
1
@ Stephan202: Sayangnya, koleksi ABC tinggal collections, tetapi sebaliknya saran yang bagus
u0b34a0f6ae
4
Ini benar, tetapi Anda memiliki banyak ruang terbuang sebagai akibatnya, yang mengarah pada kinerja suboptimal.
Daniel Kats
3
Tambahan; collections.OrderedDict juga tersedia dalam python 2.7.
Nurbldoff
2
Melakukan OrderedSet([1,2,3])memunculkan TypeError. Bagaimana cara kerja konstruktor? Contoh penggunaan tidak ada.
xApple
90
Jawabannya adalah tidak, tetapi Anda dapat menggunakan collections.OrderedDictdari pustaka standar Python hanya dengan kunci (dan nilai sebagai None) untuk tujuan yang sama.
Update : Pada Python 3.7 (dan CPython 3.6), standar dictini dijamin untuk mempertahankan ketertiban dan lebih performant dari OrderedDict. (Namun, untuk kompatibilitas mundur dan terutama keterbacaan, Anda mungkin ingin terus menggunakan OrderedDict.)
Berikut adalah contoh cara menggunakan dictset yang dipesan untuk memfilter item duplikat sambil mempertahankan pesanan, sehingga meniru set yang dipesan. Gunakan dictmetode kelas fromkeys()untuk membuat dict, lalu cukup minta keys()kembali.
Mungkin patut disebutkan bahwa ini juga berfungsi (lebih cepat) dengan vanila dict.fromkeys(). Tetapi dalam kasus itu, urutan kunci hanya dipertahankan dalam implementasi CPython 3.6+, sehingga OrderedDictmerupakan solusi yang lebih portabel ketika pesanan penting.
Bisakah kita menyimpulkan bahwa Set dengan Python 3.7+ juga mempertahankan pesanan?
user474491
2
@ user474491 Tidak seperti dict, setdalam Python 3.7+ sayangnya tidak mempertahankan ketertiban.
cz
39
Aku bisa melakukan Anda salah satu lebih baik daripada OrderedSet: Kensington memiliki murni-Python, 2/3-kompatibel IndexedSetjenis yang tidak hanya set memerintahkan, tetapi juga mendukung pengindeksan (seperti dengan daftar).
Cukup pip install boltons(atau salin setutils.pyke basis kode Anda), impor IndexedSetdan:
>>>from boltons.setutils importIndexedSet>>> x =IndexedSet(list(range(4))+ list(range(8)))>>> x
IndexedSet([0,1,2,3,4,5,6,7])>>> x - set(range(2))IndexedSet([2,3,4,5,6,7])>>> x[-1]7>>> fcr =IndexedSet('freecreditreport.com')>>>''.join(fcr[:fcr.index('.')])'frecditpo'
Sementara yang lain telah menunjukkan bahwa tidak ada implementasi built-in dari susunan urutan penyisipan diatur dalam Python (belum), saya merasa bahwa pertanyaan ini tidak ada jawaban yang menyatakan apa yang bisa ditemukan di PyPI .
Jika Anda menggunakan set yang dipesan untuk mempertahankan pesanan yang diurutkan, pertimbangkan untuk menggunakan implementasi yang diurutkan dari PyPI. The sortedcontainers modul menyediakan SortedSet hanya untuk tujuan ini. Beberapa manfaat: implementasi murni-Python, cepat-sebagai-C, cakupan uji unit 100%, jam pengujian stres.
Menginstal dari PyPI mudah dengan pip:
pip install sortedcontainers
Perhatikan bahwa jika Anda tidak bisa pip install, cukup tarik ke bawah file sortlist.py dan sortir.py dari repositori open-source .
Setelah diinstal Anda cukup:
from sortedcontainers importSortedSet
help(SortedSet)
Modul wadah yang diurutkan juga mempertahankan perbandingan kinerja dengan beberapa implementasi alternatif.
Untuk komentar yang bertanya tentang tipe data tas Python, ada alternatifnya tipe data SortedList yang dapat digunakan untuk mengimplementasikan tas secara efisien.
Perhatikan bahwa SortedSetkelas di sana mengharuskan anggota untuk dapat dibandingkan dan hashable.
gsnedders
4
@gsnedders The builtin setdan frozensetjuga membutuhkan elemen yang harus hashable. Batasan yang sebanding adalah tambahan untuk SortedSet, tetapi juga kendala yang jelas.
keturunan
2
Seperti namanya, ini tidak menjaga ketertiban. Itu tidak lain adalah diurutkan (set ([urutan])) yang membuat lebih baik?
ldmtwo
@ldmtwo Saya tidak yakin yang Anda maksud tetapi hanya untuk menjadi jelas, SortedSet sebagai bagian dari Container Diurutkan memang mempertahankan urutan diurutkan.
GrantJ
2
@GrantJ - Ini adalah perbedaan antara apakah ia mempertahankan penyisipan perintah atau semacam order. Sebagian besar jawaban lain adalah mengenai urutan penyisipan. Saya pikir Anda sudah mengetahui hal ini berdasarkan kalimat pertama Anda, tetapi mungkin itulah yang dikatakan oleh ldmtwo.
Justin
9
Jika Anda sudah menggunakan panda dalam kode Anda, Indexobjeknya berperilaku cukup seperti set yang diperintahkan, seperti yang ditunjukkan dalam artikel ini .
Bisakah Anda memasukkan contoh dalam jawaban ini? Tautan cenderung rusak setelah beberapa waktu.
Alechan
1
untuk perbedaan antara set, Anda benar-benar perlu menggunakan indA.difference(indB), tanda minus melakukan pengurangan standar
gg349
7
Sedikit terlambat ke permainan, tapi saya telah menulis sebuah kelas setlistsebagai bagian dari collections-extendedsepenuhnya mengimplementasikan keduanya SequencedanSet
>>>from collections_extended import setlist
>>> sl = setlist('abracadabra')>>> sl
setlist(('a','b','r','c','d'))>>> sl[3]'c'>>> sl[-1]'d'>>>'r'in sl # testing for inclusion is fastTrue>>> sl.index('d')# so is finding the index of an element4>>> sl.insert(1,'d')# inserting an element already in raises a ValueErrorValueError>>> sl.index('d')4
The ParallelRegression paket menyediakan setlist () memerintahkan kelas set yang lebih metode-lengkap daripada pilihan berdasarkan resep ActiveState. Ini mendukung semua metode yang tersedia untuk daftar dan kebanyakan jika tidak semua metode tersedia untuk set.
Seperti jawaban lain menyebutkan, untuk python 3.7+, dikt disusun berdasarkan definisi. Alih-alih subklas OrderedDictkita dapat mensubklas abc.collections.MutableSetatau typing.MutableSetmenggunakan kunci dict untuk menyimpan nilai-nilai kita.
classOrderedSet(typing.MutableSet[T]):"""A set that preserves insertion order by internally using a dict."""def __init__(self, iterable: t.Iterator[T]):
self._d = dict.fromkeys(iterable)def add(self, x: T)->None:
self._d[x]=Nonedef discard(self, x: T)->None:
self._d.pop(x)def __contains__(self, x: object)-> bool:return self._d.__contains__(x)def __len__(self)-> int:return self._d.__len__()def __iter__(self)-> t.Iterator[T]:return self._d.__iter__()
Maka cukup:
x =OrderedSet([1,2,-1,"bar"])
x.add(0)assert list(x)==[1,2,-1,"bar",0]
Untuk banyak tujuan, cukup menelepon saja sudah cukup. Sebagai contoh
>>> s = set([0,1,2,99,4,40,3,20,24,100,60])>>> sorted(s)[0,1,2,3,4,20,24,40,60,99,100]
Jika Anda akan menggunakan ini berulang kali, akan ada overhead yang muncul dengan memanggil fungsi yang diurutkan sehingga Anda mungkin ingin menyimpan daftar yang dihasilkan, selama Anda selesai mengubah set. Jika Anda perlu mempertahankan elemen unik dan diurutkan, saya setuju dengan saran untuk menggunakan OrderedDict dari koleksi dengan nilai arbitrer seperti Tidak Ada.
Tujuan untuk OrderedSet adalah untuk bisa mendapatkan item dalam urutan yang mereka tambahkan ke set. Contoh Anda mungkin bisa disebut SortedSet ...
Pemeliharaan Berkala
-4
Jadi saya juga punya daftar kecil di mana saya jelas memiliki kemungkinan memperkenalkan nilai-nilai yang tidak unik.
Saya mencari keberadaan daftar unik dari beberapa jenis, tetapi kemudian menyadari bahwa menguji keberadaan elemen sebelum menambahkannya berfungsi dengan baik.
if(not new_element in my_list):
my_list.append(new_element)
Saya tidak tahu apakah ada peringatan untuk pendekatan sederhana ini, tetapi itu memecahkan masalah saya.
Masalah utama dengan pendekatan ini adalah menambahkan berjalan di O (n). Artinya semakin lambat dengan daftar besar. Set built-in Python sangat baik dalam membuat penambahan elemen lebih cepat. Tetapi untuk kasus penggunaan yang sederhana, tentu saja itu berhasil!
collections.Counter
adalah tas Python.Jawaban:
Ada resep yang diatur (mungkin tautan baru ) resep untuk ini yang dirujuk dari Dokumentasi Python 2 . Ini berjalan pada Py2.6 atau lebih baru dan 3.0 atau lebih baru tanpa modifikasi apa pun. Antarmuka hampir persis sama dengan set normal, kecuali bahwa inisialisasi harus dilakukan dengan daftar.
Ini adalah MutableSet, jadi tanda tangan untuk
.union
tidak cocok dengan yang ditetapkan, tetapi karena menyertakan__or__
sesuatu yang serupa dapat dengan mudah ditambahkan:sumber
update
,union
,intersection
.union
dalam kelas yang sama. Yang terakhir akan "menang" dan yang pertama akan gagal ada saat runtime. Ini karenaOrderedSet.union
(tanpa parens) harus merujuk ke satu objek.Set yang dipesan secara fungsional merupakan kasus khusus dari kamus yang diurutkan.
Kunci-kunci kamus itu unik. Jadi, jika seseorang mengabaikan nilai-nilai dalam kamus yang diurutkan (misalnya dengan menetapkannya
None
), maka pada dasarnya ia memiliki kumpulan yang diurutkan.Pada Python 3.1 ada
collections.OrderedDict
. Berikut ini adalah contoh implementasi dari OrderedSet. (Perhatikan bahwa hanya beberapa metode yang perlu didefinisikan atau diganti:collections.OrderedDict
dancollections.MutableSet
lakukan pengangkatan berat.)sumber
OrderedSet
yang subclassOrderedDict
danabc.Set
kemudian menentukan__len__
,__iter__
dan__contains__
.collections
, tetapi sebaliknya saran yang bagusOrderedSet([1,2,3])
memunculkan TypeError. Bagaimana cara kerja konstruktor? Contoh penggunaan tidak ada.Jawabannya adalah tidak, tetapi Anda dapat menggunakan
collections.OrderedDict
dari pustaka standar Python hanya dengan kunci (dan nilai sebagaiNone
) untuk tujuan yang sama.Update : Pada Python 3.7 (dan CPython 3.6), standar
dict
ini dijamin untuk mempertahankan ketertiban dan lebih performant dariOrderedDict
. (Namun, untuk kompatibilitas mundur dan terutama keterbacaan, Anda mungkin ingin terus menggunakanOrderedDict
.)Berikut adalah contoh cara menggunakan
dict
set yang dipesan untuk memfilter item duplikat sambil mempertahankan pesanan, sehingga meniru set yang dipesan. Gunakandict
metode kelasfromkeys()
untuk membuat dict, lalu cukup mintakeys()
kembali.sumber
dict.fromkeys()
. Tetapi dalam kasus itu, urutan kunci hanya dipertahankan dalam implementasi CPython 3.6+, sehinggaOrderedDict
merupakan solusi yang lebih portabel ketika pesanan penting.keys = (1,2,3,1,2,1)
list(OrderedDict.fromkeys(keys).keys())
->[1, 2, 3]
, python-3.7. Berhasil.dict
,set
dalam Python 3.7+ sayangnya tidak mempertahankan ketertiban.Aku bisa melakukan Anda salah satu lebih baik daripada OrderedSet: Kensington memiliki murni-Python, 2/3-kompatibel
IndexedSet
jenis yang tidak hanya set memerintahkan, tetapi juga mendukung pengindeksan (seperti dengan daftar).Cukup
pip install boltons
(atau salinsetutils.py
ke basis kode Anda), imporIndexedSet
dan:Semuanya unik dan tetap teratur. Pengungkapan penuh: Saya menulis
IndexedSet
, tetapi itu juga berarti Anda dapat menggangguku jika ada masalah . :)sumber
Implementasi pada PyPI
Sementara yang lain telah menunjukkan bahwa tidak ada implementasi built-in dari susunan urutan penyisipan diatur dalam Python (belum), saya merasa bahwa pertanyaan ini tidak ada jawaban yang menyatakan apa yang bisa ditemukan di PyPI .
Ada paketnya:
Beberapa implementasi ini didasarkan pada resep yang diposting oleh Raymond Hettinger ke ActiveState yang juga disebutkan dalam jawaban lain di sini.
Beberapa perbedaan
my_set[5]
)remove(item)
Kedua implementasi memiliki O (1) untuk
add(item)
dan__contains__(item)
(item in my_set
).sumber
set.union
tidak berfungsi meskipun, meskipun mewarisicollections.abc.Set
.OrderedSet
sekarang mendukungremove
Jika Anda menggunakan set yang dipesan untuk mempertahankan pesanan yang diurutkan, pertimbangkan untuk menggunakan implementasi yang diurutkan dari PyPI. The sortedcontainers modul menyediakan SortedSet hanya untuk tujuan ini. Beberapa manfaat: implementasi murni-Python, cepat-sebagai-C, cakupan uji unit 100%, jam pengujian stres.
Menginstal dari PyPI mudah dengan pip:
Perhatikan bahwa jika Anda tidak bisa
pip install
, cukup tarik ke bawah file sortlist.py dan sortir.py dari repositori open-source .Setelah diinstal Anda cukup:
Modul wadah yang diurutkan juga mempertahankan perbandingan kinerja dengan beberapa implementasi alternatif.
Untuk komentar yang bertanya tentang tipe data tas Python, ada alternatifnya tipe data SortedList yang dapat digunakan untuk mengimplementasikan tas secara efisien.
sumber
SortedSet
kelas di sana mengharuskan anggota untuk dapat dibandingkan dan hashable.set
danfrozenset
juga membutuhkan elemen yang harus hashable. Batasan yang sebanding adalah tambahan untukSortedSet
, tetapi juga kendala yang jelas.Jika Anda sudah menggunakan panda dalam kode Anda,
Index
objeknya berperilaku cukup seperti set yang diperintahkan, seperti yang ditunjukkan dalam artikel ini .Contoh dari artikel:
sumber
indA.difference(indB)
, tanda minus melakukan pengurangan standarSedikit terlambat ke permainan, tapi saya telah menulis sebuah kelas
setlist
sebagai bagian daricollections-extended
sepenuhnya mengimplementasikan keduanyaSequence
danSet
GitHub: https://github.com/mlenzen/collections-extended
Dokumentasi: http://collections-extended.lenzm.net/en/latest/
PyPI: https://pypi.python.org/pypi/collections-extended
sumber
Tidak ada
OrderedSet
di perpustakaan resmi. Saya membuat lembar contekan lengkap dari semua struktur data untuk referensi Anda.sumber
The ParallelRegression paket menyediakan setlist () memerintahkan kelas set yang lebih metode-lengkap daripada pilihan berdasarkan resep ActiveState. Ini mendukung semua metode yang tersedia untuk daftar dan kebanyakan jika tidak semua metode tersedia untuk set.
sumber
Seperti jawaban lain menyebutkan, untuk python 3.7+, dikt disusun berdasarkan definisi. Alih-alih subklas
OrderedDict
kita dapat mensubklasabc.collections.MutableSet
atautyping.MutableSet
menggunakan kunci dict untuk menyimpan nilai-nilai kita.Maka cukup:
Saya meletakkan kode ini di perpustakaan kecil , jadi siapa pun bisa
pip install
melakukannya.sumber
Untuk banyak tujuan, cukup menelepon saja sudah cukup. Sebagai contoh
Jika Anda akan menggunakan ini berulang kali, akan ada overhead yang muncul dengan memanggil fungsi yang diurutkan sehingga Anda mungkin ingin menyimpan daftar yang dihasilkan, selama Anda selesai mengubah set. Jika Anda perlu mempertahankan elemen unik dan diurutkan, saya setuju dengan saran untuk menggunakan OrderedDict dari koleksi dengan nilai arbitrer seperti Tidak Ada.
sumber
Jadi saya juga punya daftar kecil di mana saya jelas memiliki kemungkinan memperkenalkan nilai-nilai yang tidak unik.
Saya mencari keberadaan daftar unik dari beberapa jenis, tetapi kemudian menyadari bahwa menguji keberadaan elemen sebelum menambahkannya berfungsi dengan baik.
Saya tidak tahu apakah ada peringatan untuk pendekatan sederhana ini, tetapi itu memecahkan masalah saya.
sumber