क्या पायथन के पास एक निर्धारित सेट है?


477

पायथन में एक आदेशित शब्दकोश है । एक ऑर्डर किए गए सेट के बारे में क्या?


18
आक्षेप के बारे में, चीजों का एक बैग? (अव्यवस्थित और गैर-अद्वितीय)
विम

19
@wim collections.Counterअजगर का बैग है।
फटा

1
अगर कोई चीज दो बार जुड़ जाए तो क्या होगा? स्थिति क्या होनी चाहिए?
मैकके

2
@McKay - यदि यह संग्रह के व्यवहार का पालन करने के लिए थे। इसके अलावा यह अभी भी प्रारंभिक जोड़ की स्थिति में होगा
wojtow

जवाबों:


206

इसके लिए एक ऑर्डर किया हुआ सेट (संभावित नया लिंक ) नुस्खा है जिसे पायथन 2 डॉक्यूमेंटेशन से संदर्भित किया गया है । यह Py2.6 या बाद में और 3.0 या बाद में बिना किसी संशोधन के चलता है। इंटरफ़ेस लगभग एक सामान्य सेट के समान है, सिवाय इसके कि एक सूची के साथ आरंभीकरण किया जाना चाहिए।

OrderedSet([1, 2, 3])

यह एक MutableSet है, इसलिए इसके लिए हस्ताक्षर .unionसेट के मेल से मेल नहीं खाता है, लेकिन चूंकि इसमें __or__कुछ ऐसा ही शामिल है जो आसानी से जोड़ा जा सकता है:

@staticmethod
def union(*sets):
    union = OrderedSet()
    union.union(*sets)
    return union

def union(self, *sets):
    for set in sets:
        self |= set

6
मैंने अपना स्वयं का उत्तर चुना क्योंकि प्रलेखन से संदर्भ आधिकारिक उत्तर के करीब है
केसबश

49
इंटरफ़ेस बिल्कुल सामान्य सेट वस्तु के रूप में ही नहीं है, कई आवश्यक तरीकों के रूप में इस तरह के याद कर रहे हैं update, union, intersection
xApple

5
FYI करें, मैंने देखा कि इस उत्तर में दिए गए नुस्खा का थोड़ा संशोधित संस्करण "ऑर्डर-सेट" के रूप में PyPi में जोड़ा गया है
ज्योफ्री हिंग

7
मुझे पूरा यकीन है कि आपको unionएक ही कक्षा में दो तरीकों से दोनों को बुलाए जाने की अनुमति नहीं है । अंतिम एक "जीत" होगा और पहले वाला रनटाइम में मौजूद नहीं रहेगा। ऐसा इसलिए है क्योंकि OrderedSet.union(किसी भी परेंस को) किसी एक ऑब्जेक्ट को रेफर नहीं करना है ।
केविन

3
"ऑर्डरसेट" पैकेज भी है जो एक ही रेसिपी पर आधारित है लेकिन साइथन - pypi.python.org/pypi/orderedset में लागू किया गया है ।
mbdevpl

149

एक आदेश दिया सेट कार्यात्मक रूप से एक आदेशित शब्दकोश का एक विशेष मामला है।

एक शब्दकोश की कुंजी अद्वितीय हैं। इस प्रकार, यदि कोई एक ऑर्डर किए गए शब्दकोश (जैसे उन्हें असाइन करके None) में मानों की अवहेलना करता है , तो एक अनिवार्य रूप से एक आदेशित सेट है।

पायथन 3.1 के रूप में है collections.OrderedDict। निम्नलिखित एक ऑर्डरेडसेट का एक उदाहरण कार्यान्वयन है। (ध्यान दें कि केवल कुछ तरीकों को परिभाषित करने या ओवरराइड करने की आवश्यकता है: collections.OrderedDictऔर collections.MutableSetभारी उठाने की आवश्यकता है।)

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__

1
@Casebash: हाँ, एक एक वर्ग को परिभाषित कर सकते हैं OrderedSetजो उपवर्गों OrderedDictऔर abc.Setऔर फिर परिभाषित __len__, __iter__और __contains__
Stephan202

1
@ Stephan202: अफसोस, संग्रह ABCs में रहते हैं collections, लेकिन अन्यथा एक अच्छा सुझाव
u0b34a0f6ae

4
यह सच है, लेकिन आपके पास बहुत सारे व्यर्थ स्थान हैं नतीजतन, जो उप-प्रदर्शन को आगे बढ़ाता है।
डैनियल कैट्स

3
जोड़; संग्रह। ट्रेडेड डिक्टेट भी अजगर 2.7 में उपलब्ध है।
नर्बल्डॉफ

2
करना OrderedSet([1,2,3])एक प्रकार से बढ़ाता है। कंस्ट्रक्टर भी कैसे काम करता है? मिसिंग उपयोग उदाहरण।
xApple

90

इसका उत्तर नहीं है, लेकिन आप collections.OrderedDictपायथन मानक पुस्तकालय Noneसे एक ही उद्देश्य के लिए सिर्फ चाबियाँ (और मान के रूप में ) का उपयोग कर सकते हैं ।

अपडेट : पायथन 3.7 (और सीपीथॉन 3.6) के रूप में, मानक dictको ऑर्डर को संरक्षित करने की गारंटी है और की तुलना में अधिक प्रदर्शनकारी है OrderedDict। (पिछड़ी अनुकूलता और विशेष रूप से पठनीयता के लिए, हालाँकि, आप का उपयोग जारी रखना चाह सकते हैं OrderedDict।)

dictआदेश का संरक्षण करते हुए डुप्लिकेट आइटम को फ़िल्टर करने के लिए एक सेट सेट के रूप में उपयोग करने का एक उदाहरण यहां दिया गया है, जिससे ऑर्डर किए गए सेट का अनुकरण किया जा सकता है। एक तानाशाह बनाने के लिए dictकक्षा पद्धति fromkeys()का उपयोग करें , फिर बस keys()पीठ के लिए पूछें ।

>>> keywords = ['foo', 'bar', 'bar', 'foo', 'baz', 'foo']

>>> list(dict.fromkeys(keywords))
['foo', 'bar', 'baz']

4
शायद यह ध्यान देने योग्य है कि यह वेनिला के साथ भी (तेजी से) काम करता है dict.fromkeys()। लेकिन उस मामले में, कुंजी ऑर्डर केवल CPython 3.6+ कार्यान्वयन में संरक्षित है, इसलिए OrderedDictऑर्डर के मामले में एक अधिक पोर्टेबल समाधान है।
jez

1
मान स्ट्रिंग नहीं हैं तो काम नहीं करेंगे
अनवर हुसैन

4
@AnwarHossain keys = (1,2,3,1,2,1) list(OrderedDict.fromkeys(keys).keys())-> [1, 2, 3], अजगर -३.९। यह काम करता हैं।
रतीरु

1
क्या हम उस सेट को पाइथन 3.7+ में भी संरक्षित कर सकते हैं जो ऑर्डर को संरक्षित करता है?
user474491

2
@ user474491 विपरीत dict, setपायथन में 3.7+ दुर्भाग्य से आदेश को संरक्षित नहीं करता है।
cz

39

मैं आपको एक ऑर्डरेडसेट से बेहतर कर सकता हूं: बोल्ट में शुद्ध-पायथन, 2/3-संगत IndexedSetप्रकार है जो न केवल एक ऑर्डर सेट है, बल्कि अनुक्रमण (सूचियों के साथ) का भी समर्थन करता है।

बस pip install boltons(या setutils.pyअपने कोडबेस में कॉपी करें), आयात करें IndexedSetऔर:

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

सब कुछ अद्वितीय और क्रम में बनाए रखा जाता है। पूर्ण प्रकटीकरण: मैंने लिखा था IndexedSet, लेकिन इसका मतलब यह भी है कि अगर कोई समस्या है तो आप मुझे बग कर सकते हैं । :)


39

PyPI पर कार्यान्वयन

हालांकि अन्य लोगों ने बताया है कि पायथन (अभी तक) में एक सम्मिलन-आदेश संरक्षण संरक्षण के कार्यान्वयन में कोई अंतर्निहित नहीं है, मुझे लग रहा है कि यह प्रश्न एक उत्तर याद कर रहा है जो बताता है कि PyPI पर क्या पाया जाना है

पैकेज हैं:

इनमें से कुछ कार्यान्वयन रेमंड हेटिंगर द्वारा ActiveState में पोस्ट की गई रेसिपी पर आधारित हैं जिसका उल्लेख यहाँ अन्य उत्तरों में भी किया गया है।

कुछ अंतर

  • ऑर्डर-सेट (संस्करण 1.1)
    • लाभ: O (1) अनुक्रमणिका द्वारा लुकअप के लिए (जैसे my_set[5])
  • ओसेट (संस्करण 0.1.3)
    • लाभ: ओ (1) के लिए remove(item)
    • नुकसान: जाहिरा तौर पर ओ (एन) सूचकांक द्वारा लुकअप के लिए

दोनों कार्यान्वयन हे (1) के लिए है add(item)और __contains__(item)( item in my_set)।


2
एक नया दावेदार collection_extended.setlist है । कार्य इस set.unionपर काम नहीं करते हैं, भले ही यह विरासत में मिलता है collections.abc.Set
तैमिलाल

3
OrderedSetअब समर्थन करता हैremove
युद्ध

17

यदि आप क्रमबद्ध क्रम को बनाए रखने के लिए सेट किए गए सेट का उपयोग कर रहे हैं, तो PyPI से सॉर्ट किए गए सेट कार्यान्वयन का उपयोग करने पर विचार करें। Sortedcontainers मॉड्यूल एक प्रदान करता है SortedSet सिर्फ इस उद्देश्य के लिए। कुछ लाभ: शुद्ध-पायथन, तेज़-एस-सी कार्यान्वयन, 100% यूनिट परीक्षण कवरेज, तनाव परीक्षण के घंटे।

PyPI से स्थापित करना पाइप से आसान है:

pip install sortedcontainers

ध्यान दें कि यदि आप नहीं कर सकते pip install , तो केवल ओपन-सोर्स रिपॉजिटरी से सॉर्टलिस्टलिस्ट और सॉर्टसेटसेट ओरेकल को नीचे खींचें ।

एक बार स्थापित करने के बाद आप बस:

from sortedcontainers import SortedSet
help(SortedSet)

Sortedcontainers मॉड्यूल भी एक बनाए रखता है कई वैकल्पिक कार्यान्वयन के साथ प्रदर्शन की तुलना है।

पायथन के बैग डेटा प्रकार के बारे में पूछने वाली टिप्पणी के लिए, वैकल्पिक रूप से एक SortedList डेटा प्रकार है, जो कुशलतापूर्वक एक बैग को लागू करने के लिए इस्तेमाल किया जा सकता है।


ध्यान दें कि SortedSetवहाँ के वर्ग को सदस्यों की तुलना करने योग्य और धोने योग्य बनाने की आवश्यकता है।
gsnedders

4
@gsnedders बिल्डिंस setऔर frozensetतत्वों को धोने योग्य होने की भी आवश्यकता होती है। तुलनीय बाधा के लिए जोड़ है SortedSet, लेकिन यह भी एक स्पष्ट बाधा है।
gotgenes

2
जैसा कि नाम से पता चलता है, यह आदेश बनाए नहीं रखता है। यह सॉर्ट (सेट ([अनुक्रम))) के अलावा कुछ नहीं है जो बेहतर बनाता है?
ldmtwo

@ldmtwo मुझे यकीन नहीं है कि आप किसका जिक्र कर रहे हैं लेकिन सिर्फ स्पष्ट होने के लिए, SortedSet सॉर्ट किए गए कंटेनरों के हिस्से के रूप में क्रमबद्ध क्रम बनाए रखें।
ग्रांटज

2
@GrantJ - यह है कि क्या यह कहना है के बीच अंतर है प्रविष्टि के आदेश या प्रकार आदेश। अन्य जवाबों में से अधिकांश प्रविष्टि आदेश के बारे में हैं। मुझे लगता है कि आप पहले से ही अपने पहले वाक्य के आधार पर इसके बारे में जानते हैं, लेकिन यह शायद ldmtwo क्या कह रहा है।
जस्टिन

8

यदि आप पहले से ही अपने कोड में पांडा का उपयोग कर रहे हैं, तो इसका Indexऑब्जेक्ट एक ऑर्डर किए गए सेट की तरह ही व्यवहार करता है, जैसा कि इस लेख में दिखाया गया है ।

लेख के उदाहरण:

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

क्या आप इस उत्तर में एक उदाहरण शामिल कर सकते हैं? लिंक कुछ समय बाद टूट जाते हैं।
अलेचन

1
सेट के बीच के अंतर के लिए, आपको वास्तव में उपयोग करने की आवश्यकता है indA.difference(indB), ऋण चिह्न मानक घटाव करता है
gg349

7

खेल में थोड़ी देर हो गई है, लेकिन मैंने उस वर्ग setlistके हिस्से के रूप में लिखा है collections-extendedजो पूरी तरह से दोनों को लागू करता है SequenceऔरSet

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

प्रलेखन: http://collections-extended.lenzm.net/en/latest/

PyPI: https://pypi.python.org/pypi/collections-extended


7

OrderedSetआधिकारिक पुस्तकालय में कोई नहीं है। मैं आपके संदर्भ के लिए सभी डेटा संरचना की एक विस्तृत धोखा देती हूं।

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']
}

3

ParallelRegression पैकेज एक प्रदान करता है सेटलिस्ट () सेट वर्ग और अधिक विधि: पूर्ण विकल्प ActiveState नुस्खा के आधार पर की तुलना में है कि आदेश दिया। यह सूचियों के लिए उपलब्ध सभी तरीकों का समर्थन करता है और सबसे अधिक अगर सेट के लिए उपलब्ध सभी तरीकों का नहीं।


2

जैसा कि अन्य जवाबों में बताया गया है कि अजगर 3.7+ के लिए, हुकुम को परिभाषा द्वारा आदेशित किया गया है। इसके बजाय उपवर्गीकरण की OrderedDictहम उपवर्ग कर सकते हैं abc.collections.MutableSetया typing.MutableSetहमारे मूल्यों को स्टोर करने के dict की कुंजियों का उपयोग।

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

फिर बस:

x = OrderedSet([1, 2, -1, "bar"])
x.add(0)
assert list(x) == [1, 2, -1, "bar", 0]

मैंने इस कोड को एक छोटे से पुस्तकालय में रखा है , इसलिए कोई भी इसे बस कर सकता pip installहै।


-4

कई उद्देश्यों के लिए बस सॉर्टिंग पर्याप्त होगी। उदाहरण के लिए

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

यदि आप इसे बार-बार उपयोग करने जा रहे हैं, तो सॉर्ट किए गए फ़ंक्शन को कॉल करके ओवरहेड हो जाएगा, ताकि आप परिणामी सूची को सहेजना चाहें, जब तक कि आप सेट को बदलते रहें। यदि आपको अद्वितीय तत्वों को बनाए रखने और क्रमबद्ध करने की आवश्यकता है, तो मैं किसी भी तरह के मनमाने मूल्य के साथ संग्रह से ऑर्डरडेड का उपयोग करने के सुझाव से सहमत हूं।


43
ऑर्डरडसेट का उद्देश्य उन वस्तुओं को प्राप्त करने में सक्षम होना है जो उन्होंने सेट में जोड़े थे। आप उदाहरण शायद सॉर्टेडसेट कह सकते हैं ...
आवधिक रखरखाव

-4

इसलिए मेरे पास एक छोटी सूची भी थी जहां मुझे स्पष्ट रूप से गैर-अद्वितीय मूल्यों को पेश करने की संभावना थी।

मैंने किसी प्रकार की एक अनूठी सूची के अस्तित्व की खोज की, लेकिन फिर महसूस किया कि तत्व के अस्तित्व को जोड़ने से पहले परीक्षण करना ठीक काम करता है।

if(not new_element in my_list):
    my_list.append(new_element)

मैं नहीं जानता कि क्या इस सरल दृष्टिकोण के लिए चेतावनी हैं, लेकिन यह मेरी समस्या को हल करता है।


इस दृष्टिकोण के साथ मुख्य मुद्दा यह है कि ओ (एन) में रन जोड़ना। मतलब यह बड़ी सूचियों के साथ धीमी हो जाती है। पायथन के अंतर्निर्मित सेट तेजी से तत्वों को जोड़ने में बहुत अच्छे हैं। लेकिन सरल उपयोग के मामलों के लिए, यह निश्चित रूप से काम करता है!
ड्रेकोनिस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.