Python'un sıralı bir sözlüğü var . Sipariş edilen sete ne dersiniz?
collections.Counter
Python'un çantası.
Python'un sıralı bir sözlüğü var . Sipariş edilen sete ne dersiniz?
collections.Counter
Python'un çantası.
Yanıtlar:
Bunun için Python 2 Dokümantasyonundan atıfta bulunulan sıralı bir set (olası yeni bağlantı ) tarifi vardır . Bu, herhangi bir değişiklik yapılmadan Py2.6 veya üstü ve 3.0 veya üstü üzerinde çalışır. Başlatma işleminin bir liste ile yapılması dışında arayüz normal bir setle neredeyse tamamen aynıdır.
OrderedSet([1, 2, 3])
Bu bir MutableSet, bu nedenle imzası kümeninkiyle eşleşmiyor, .union
ancak __or__
benzer bir şey içerdiğinden kolayca eklenebilir:
@staticmethod
def union(*sets):
union = OrderedSet()
union.union(*sets)
return union
def union(self, *sets):
for set in sets:
self |= set
update
, union
, intersection
.
union
de aynı sınıfta çağırılmasına izin verilmediğinden eminim . Sonuncusu "kazanır" ve birincisi çalışma zamanında var olmaz. Çünkü OrderedSet.union
(parens yok) tek bir nesneye gönderme yapmak zorundadır .
Bir sözlüğün anahtarları benzersizdir. Dolayısıyla, biri sıralı bir sözlükteki değerleri göz ardı ederse (örneğin atayarak None
), o zaman esasen sıralı bir kümeye sahiptir.
Python 3.1 itibariyle yoktur collections.OrderedDict
. Aşağıda bir OrderedSet uygulamasının örneği yer almaktadır. (Sadece birkaç yöntemin tanımlanması veya geçersiz kılınması gerektiğini unutmayın: collections.OrderedDict
ve collections.MutableSet
ağır kaldırmayı yapın.)
import collections
class OrderedSet(collections.OrderedDict, collections.MutableSet):
def update(self, *args, **kwargs):
if kwargs:
raise TypeError("update() takes no keyword arguments")
for s in args:
for e in s:
self.add(e)
def add(self, elem):
self[elem] = None
def 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__
OrderedSet
hangi alt sınıfları OrderedDict
ve abc.Set
ardından tanımlamak __len__
, __iter__
ve __contains__
.
collections
, ama aksi halde iyi bir öneri
OrderedSet([1,2,3])
bir TypeError hatası yükseltir. Yapıcı nasıl çalışır? Eksik kullanım örneği.
Cevap hayırdır, ancak collections.OrderedDict
Python standart kütüphanesinden None
aynı amaç için sadece anahtarları (ve değerleri ) kullanabilirsiniz.
Güncelleme : Python 3.7 (ve CPython 3.6) itibariyle, standart siparişi koruyacakdict
şekilde garanti edilir ve daha fazla performans gösterir OrderedDict
. (Ancak geriye dönük uyumluluk ve özellikle okunabilirlik için kullanmaya devam etmek isteyebilirsiniz OrderedDict
.)
Aşağıda dict
, sipariş korunurken yinelenen öğeleri filtrelemek ve böylece sıralı bir seti taklit etmek için sıralı bir set olarak nasıl kullanılacağına dair bir örnek verilmiştir . Bir diksiyon oluşturmak için dict
class yöntemini kullanın fromkeys()
, sonra sadece keys()
arka istemek .
>>> keywords = ['foo', 'bar', 'bar', 'foo', 'baz', 'foo']
>>> list(dict.fromkeys(keywords))
['foo', 'bar', 'baz']
dict.fromkeys()
. Ancak bu durumda, anahtar sipariş yalnızca CPython 3.6+ uygulamalarında korunur, bu nedenle OrderedDict
sipariş önemli olduğunda daha taşınabilir bir çözümdür.
keys = (1,2,3,1,2,1)
list(OrderedDict.fromkeys(keys).keys())
-> [1, 2, 3]
, python-3.7. İşe yarıyor.
dict
, set
Python 3.7+ 'de maalesef düzeni korumaz.
Size bir OrderedSet daha iyi yapabilirim: boltons saf-Python,IndexedSet
sadece sıralı bir set değil, aynı zamanda indekslemeyi (listelerde olduğu gibi) destekleyen 2/3 uyumlu bir türe sahiptir.
Basitçe pip install boltons
(veya setutils.py
kod tabanınıza kopyalayın ) IndexedSet
ve:
>>> from boltons.setutils import IndexedSet
>>> 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'
Her şey benzersizdir ve sırayla korunur. Tam açıklama: Ben yazdım IndexedSet
, ama aynı zamanda herhangi bir sorun varsa beni rahatsız edebileceğiniz anlamına gelir . :)
Diğerleri, Python'da (henüz) bir yerleştirme siparişi korumasının yerleşik bir uygulaması olmadığını belirtmiş olsa da, bu sorunun PyPI'de ne bulunacağını belirten bir cevabı eksik olduğunu hissediyorum .
Paketler var:
Bu uygulamalardan bazıları, Raymond Hettinger tarafından ActiveState'e gönderilen ve buradaki diğer cevaplarda da belirtilen tarife dayanmaktadır .
my_set[5]
)remove(item)
Her iki uygulamada add(item)
ve __contains__(item)
( item in my_set
) için O (1 ) vardır.
set.union
miras olsa da üzerinde çalışmıyor collections.abc.Set
.
Sıralı seti korumak için sıralı seti kullanıyorsanız, PyPI'den sıralı set uygulaması kullanmayı düşünün. Sortedcontainers modülü sağlar SortedSet sadece bu amaç için. Bazı faydaları: saf Python, C kadar hızlı uygulamalar,% 100 birim test kapsamı, saatlerce stres testi.
Pip ile PyPI'den kurulum kolaydır:
pip install sortedcontainers
Not açamıyorsa pip install
, basitçe dan sortedlist.py ve sortedset.py dosyaları aşağı çekmek açık kaynaklı depo .
Kurulduktan sonra şunları yapabilirsiniz:
from sortedcontainers import SortedSet
help(SortedSet)
Sortcontainers modülü ayrıca çeşitli alternatif uygulamalarla bir performans karşılaştırması yapar .
Python'un torba veri türü hakkında soru soran yorum için alternatif olarak bir torbayı verimli bir şekilde uygulamak için kullanılabilecek bir SortedList veri türü vardır.
SortedSet
sınıf karşılaştırılabilir ve hashable olmasını üyelerini orada gerektirir.
set
ve frozenset
ayrıca elemanların yıkanabilir olmasını gerektirir. Karşılaştırılabilir kısıtlama eklentidir SortedSet
, ancak aynı zamanda bariz bir kısıtlamadır.
Kodunuzda zaten panda kullanıyorsanız, Index
nesnesi bu makalede gösterildiği gibi sıralı bir küme gibi davranır .
Makaleden örnekler:
indA = pd.Index([1, 3, 5, 7, 9])
indB = pd.Index([2, 3, 5, 7, 11])
indA & indB # intersection
indA | indB # union
indA - indB # difference
indA ^ indB # symmetric difference
indA.difference(indB)
, eksi işareti standart çıkarma yapar
Geç oyuna Biraz ama ben bir sınıf yazdım setlist
bir parçası olarak collections-extended
o tamamen uygular hem Sequence
veSet
>>> 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 fast
True
>>> sl.index('d') # so is finding the index of an element
4
>>> sl.insert(1, 'd') # inserting an element already in raises a ValueError
ValueError
>>> sl.index('d')
4
GitHub: https://github.com/mlenzen/collections-extended
Hiçbir Orada OrderedSet
resmi kütüphanede. Referansınız için tüm veri yapısının kapsamlı bir hile sayfasını hazırladım.
DataStructure = {
'Collections': {
'Map': [
('dict', 'OrderDict', 'defaultdict'),
('chainmap', 'types.MappingProxyType')
],
'Set': [('set', 'frozenset'), {'multiset': 'collection.Counter'}]
},
'Sequence': {
'Basic': ['list', 'tuple', 'iterator']
},
'Algorithm': {
'Priority': ['heapq', 'queue.PriorityQueue'],
'Queue': ['queue.Queue', 'multiprocessing.Queue'],
'Stack': ['collection.deque', 'queue.LifeQueue']
},
'text_sequence': ['str', 'byte', 'bytearray']
}
ParallelRegression paketi içerir setlist () metodu daha tamamlama ActiveState tarifi göre seçeneklerine göre ayar sınıfı vermiştir. Listeler için kullanılabilir tüm yöntemleri ve kümeler için mevcut olmasa bile çoğu yöntemi destekler.
Diğer cevapların belirttiği gibi, python 3.7+ için, söz tanım gereği sıralanmıştır. Alt sınıflandırma yerine değerlerimizi saklamak için OrderedDict
alt sınıfları kullanabilir abc.collections.MutableSet
veya typing.MutableSet
dikt tuşlarını kullanabiliriz.
class OrderedSet(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] = None
def 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__()
O zaman sadece:
x = OrderedSet([1, 2, -1, "bar"])
x.add(0)
assert list(x) == [1, 2, -1, "bar", 0]
Bu kodu küçük bir kütüphaneye koydum , böylece herkes sadece yapabilir pip install
.
Birçok amaç için sıralı çağırmak yeterli olacaktır. Örneğin
>>> 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]
Bunu tekrar tekrar kullanacaksanız, sıralanmış işlevi çağırarak genel masraf oluşacaktır, böylece seti değiştirmeyi tamamladığınız sürece sonuç listesini kaydetmek isteyebilirsiniz. Benzersiz öğeleri korumanız ve sıralamanız gerekiyorsa, Yok gibi keyfi bir değere sahip koleksiyonlardan OrderedDict kullanma önerisini kabul ediyorum.
Bu yüzden ben açıkça açıkça benzersiz olmayan değerleri tanıtmak imkanı vardı küçük bir liste vardı.
Bir tür eşsiz bir listenin varlığını araştırdım, ancak daha sonra öğenin varlığını eklemeden önce test etmenin iyi çalıştığını fark ettim.
if(not new_element in my_list):
my_list.append(new_element)
Bu basit yaklaşımda uyarılar olup olmadığını bilmiyorum, ama sorunumu çözdü.