2012-03-20 12 views
42

हाल ही में मैंने देखा कि जब मैं ऑर्डर सेट करने के लिए सूची परिवर्तित कर रहा हूं या तत्व बदल गए हैं और चरित्र द्वारा क्रमबद्ध किया गया है।तत्व ऑर्डर बदलते हैं?

इस उदाहरण पर विचार:

x=[1,2,20,6,210] 
print x 
# [1, 2, 20, 6, 210] # the order is same as initial order 

set(x) 
# set([1, 2, 20, 210, 6]) # in the set(x) output order is sorted 

मेरे सवाल कर रहे हैं -

  1. हो रहा क्यों है?
  2. प्रारंभिक क्रम खोए बिना मैं सेट ऑपरेशंस (विशेष रूप से सेट अंतर) कैसे कर सकता हूं?
+5

आप प्रारंभिक क्रम क्यों खोना नहीं चाहते हैं, खासकर यदि आप सेट ऑपरेशन कर रहे हैं? "ऑर्डर" सेट के लिए एक अर्थहीन अवधारणा है, न केवल पायथन में बल्कि गणित में। –

+46

@ करलकेचटेल - हां "आदेश सेट के लिए एक अर्थहीन अवधारणा है ... गणित में" लेकिन मेरे पास वास्तविक दुनिया की समस्याएं हैं :) –

उत्तर

50
  1. एक set एक अव्यवस्थित डेटा संरचना है।

  2. एक set, बल्कि collections.OrderedDict उपयोग न करें:

    >>> a = collections.OrderedDict.fromkeys([1, 2, 20, 6, 210]) 
    >>> b = collections.OrderedDict.fromkeys([6, 20, 1]) 
    >>> collections.OrderedDict.fromkeys(x for x in a if x not in b) 
    OrderedDict([(2, None), (210, None)]) 
    

    ध्यान दें कि b के आदेश कोई फर्क नहीं पड़ता है, इसलिए इसे किसी भी iterable हो सकता है, लेकिन यह एक iterable जो हे का समर्थन करता है होना चाहिए (1) सदस्यता परीक्षण।

संपादित: जवाब से ऊपर मानता है कि आप भी एक पूर्व निर्धारित आपरेशन के परिणाम पर, सब होने वाली संग्रह पर (आदेश दिया) सेट कार्रवाई करने में विशेष रूप से सक्षम होना चाहते हैं। यदि यह आवश्यक नहीं है, तो आप बस कुछ संग्रहों के लिए सूचियों का उपयोग कर सकते हैं, और दूसरों के लिए सेट कर सकते हैं, उदा।

>>> a = [1, 2, 20, 6, 210] 
>>> b = set([6, 20, 1]) 
>>> [x for x in a if x not in b] 
[2, 210] 

यह b के आदेश खो देता है, a और परिणाम पर तेजी से सदस्यता परीक्षण की अनुमति नहीं है। सेट्स तेजी से सदस्यता परीक्षण की अनुमति देते हैं, और सूचियां ऑर्डर देती हैं। यदि आपको एक ही संग्रह पर इन दोनों सुविधाओं की आवश्यकता है, तो collections.OrderedDict का उपयोग करें।

+0

कोई ऑब्जेक्ट लागत 16 बाइट्स नहीं है। अगर केवल एक डिफ़ॉल्ट ऑर्डरर्डसेट() है। :( – Sean

13

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

3

अन्य उत्तर में निरूपित किया जाता है के रूप में, सेट डेटा संरचनाओं (और गणितीय अवधारणाओं) उस तत्व क्रम बनाए रखने के नहीं है - सेट और शब्दकोशों का एक संयोजन का उपयोग करके,

हालांकि, यह संभव है कि आप wathever प्राप्त कर सकते हैं आप चाहते हैं - इन स्निपेट का उपयोग करके देखें: स्वेन के जवाब पर

# save the element order in a dict: 
x_dict = dict(x,y for y, x in enumerate(my_list)) 
x_set = set(my_list) 
#perform desired set operations 
... 
#retrieve ordered list from the set: 
new_list = [None] * len(new_set) 
for element in new_set: 
    new_list[x_dict[element]] = element 
1

भवन, मैं collections.OrderedDict का उपयोग कर पाया की तरह तो मेरे में मदद मिली पूरा आप क्या चाहते हैं के साथ साथ मुझे dict के लिए और अधिक आइटम जोड़ने के लिए अनुमति देते हैं:

import collections 

x=[1,2,20,6,210] 
z=collections.OrderedDict.fromkeys(x) 
z 
OrderedDict([(1, None), (2, None), (20, None), (6, None), (210, None)]) 

आप आइटम जोड़ने, लेकिन अभी भी एक सेट तुम सिर्फ कर सकते हैं जैसे कि यह इलाज करना चाहते हैं:

z['nextitem']=None 

और तुम जेड की तरह एक ऑपरेशन कर सकते हैं।dict पर कुंजी() और सेट प्राप्त:

z.keys() 
[1, 2, 20, 6, 210] 
+0

आपको सूची आउटपुट प्राप्त करने के लिए 'सूची (z.keys())' करने की आवश्यकता है। – jxn

+0

पायथन 3 में, हाँ। पायथन 2 में नहीं, हालांकि मुझे निर्दिष्ट होना चाहिए था। – jimh

-5

यहाँ यह करने के लिए एक आसान तरीका है:

x=[1,2,20,6,210] 
print sorted(set(x)) 
+2

यह आवश्यक क्रम को सुरक्षित नहीं करता है –

+1

यह उत्तर तभी सही है जब इनपुट क्रमबद्ध किया गया हो – msudder

10

अजगर 3.6 में, set() अब आदेश रखना चाहिए, लेकिन वहाँ एक और है पायथन 2 और 3:

>>> x = [1, 2, 20, 6, 210] 
>>> sorted(set(x), key=x.index) 
[1, 2, 20, 6, 210] 
+8

आदेश संरक्षण के संबंध में दो नोट्स: केवल पायथन 3.6 के रूप में, और यहां तक ​​कि, इसे कार्यान्वयन विवरण माना जाता है, इसलिए इस पर भरोसा न करें। इसके अलावा, आपका कोड बहुत है अक्षम क्योंकि प्रत्येक बार 'x.index' कहा जाता है, एक रैखिक खोज किया जाता है। यदि आप वर्गबद्ध जटिलता के साथ ठीक हैं, तो पहले स्थान पर' सेट 'का उपयोग करने का कोई कारण नहीं है। –

+9

@ तिजवानवन डीन यह गलत है, ' सेट() 'को पायथन 3.6 में आदेश नहीं दिया गया है, यहां तक ​​कि एक कार्यान्वयन विस्तार के रूप में भी नहीं, आप' dict's –

+0

@Chris_Rands के बारे में सोच रहे हैं, मैं सही खड़ा हूं; वे सम्मिलन को रखने के बजाय सॉर्ट किए गए प्रतीत होते हैं rder। किसी भी तरह से: कार्यान्वयन विस्तार। –

संबंधित मुद्दे