2017-01-02 16 views
15

मैंने सोचा कि मुझे पायथन में सूची स्लाइसिंग की मूल बातें समझी गई हैं, लेकिन एक स्लाइस पर नकारात्मक चरण का उपयोग करते समय एक अनपेक्षित त्रुटि प्राप्त हो रही है, इस प्रकार है:पायथन सूची त्रुटि: [:: - 1] चरण [: -1] स्लाइस

>>> a = list(range(10)) 
>>> a 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
>>> a[:-1] 
[0, 1, 2, 3, 4, 5, 6, 7, 8] 
>>> a[::-1] 
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0] 
>>> a[:-1:-1] 
[] 

(ध्यान दें कि यह अजगर 3.5 में चलाया जा रहा है)

क्यों नहीं एक करता है [: - 1: -1] के माध्यम से एक रिवर्स कदम [: - 1] में टुकड़ा एक ही तरीके से यह पूरी सूची के माध्यम से एक [:: - 1] के साथ करता है?

मुझे एहसास है कि आप list.reverse() का भी उपयोग कर सकते हैं, लेकिन अंतर्निहित पायथन स्लाइस कार्यक्षमता को बेहतर ढंग से समझने की कोशिश कर रहे हैं।

+1

मुझे लगता है कि आप देख रहे हैं '' एक [-1 :: - 1] ''। पहली अनुक्रमणिका शुरूआत देती है, दूसरी अनुक्रमणिका अंत देता है, और आप इंडेक्स -1 से शुरू करना चाहते हैं। – jakevdp

+0

@ekhumoro: मैंने किया, और यह काम करता है। '[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]' – Josh

+1

@ जोश। यह 'एक [:: - 1] 'से अलग कैसे है? – ekhumoro

उत्तर

19

-1a[:-1:-1] में इसका मतलब यह नहीं है कि आप क्या सोचते हैं।

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

इसका मतलब है कि

a[:-1:-1] 

a[:len(a)-1:-1] 

के बराबर जब रिवर्स टुकड़ा करने की क्रिया के दौरान छोड़ दिया गया है, len(a)-1 शुरू सूचकांक चूक,

a[len(a)-1:len(a)-1:-1] 

यह करने के लिए ऊपर बराबर बना हमेशा एक खाली सूची देता है, क्योंकि शुरुआत और अंत सूचकांक हैं वही और अंत सूचकांक अनन्य है।

में काट करने के लिए रिवर्स हुआ था और इसमें zeroth तत्व आप निम्नलिखित अंकन के किसी भी उपयोग कर सकते हैं करने के लिए:

>>> a[::-1] 
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0] 
>>> a[:None:-1] 
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0] 
>>> a[:-len(a)-1:-1] 
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0] 
+0

'a [:: - 1] ',' a [: 0: -1] ', और' a [: - 1: -1] 'के परिणामों के बीच अंतर कैसे समझाएगा? या इसे एक और तरीका डालने के लिए: खाली अंत मूल्य से वास्तविक संख्या का प्रतिनिधित्व किस प्रकार किया जाता है? – ekhumoro

+0

मुझे लगता है कि '-लेन (ए) -1' अंत का प्रतिनिधित्व करने के लिए उपयोग किया जा सकता है ('j',' a [i: j: k] ') में। यदि 'ए'' रेंज (10) 'है, तो 'एक [: - लेन (ए) -1: -1]' 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] '। यहां, '-लेन (ए) -1' -11 का मूल्यांकन करता है; यह नकारात्मक है, इसलिए इसके बजाय 'लेन (ए) + -11' का उपयोग किया जाता है ([नोट 3] (https://docs.python.org/3/library/stdtypes.html#common-sequence-operations)), जो -1 का मूल्यांकन करता है। – Josh

0

पायथन के स्लाइस पहली बार में काफी सरल लगता है, लेकिन उनके व्यवहार वास्तव में quite complex (नोट्स 3 है और 5 यहां प्रासंगिक हैं)। आप एक टुकड़ा a[i:j:k] है:

  • तो i या j नकारात्मक रहे हैं, वे a के अंत से एक सूचकांक का उल्लेख
  • तो i या j हैं (ताकि a[-1]a के अंतिम तत्व को संदर्भित करता है) निर्दिष्ट नहीं है, या None, वे a के छोर तक लागू हो रहे हैं, लेकिन जो समाप्त होता है k के हस्ताक्षर पर निर्भर करता है:

    • अगर k सकारात्मक है, तो आप आगे टुकड़ा करने की क्रिया कर रहे हैं, तो i हो जाता है 0 और j हो जाता है len(a)
    • अगर k नकारात्मक है, तो आप पीछे की ओर टुकड़ा करने की क्रिया कर रहे हैं, तो ilen(a) और j की शुरुआत से पहले तत्व बन जाता है हो जाता है a

      एनबी:j, -1 के साथ बदल नहीं किया जा सकता है के बाद से कर रही अजगर का कारण (अस्तित्वहीन) तत्व a[0] से पहले a की पिछले तत्व के बजाय j के इलाज के लिए होगा। वांछित व्यवहार पाने के लिए आपको कि a[j] को पाने के लिए, जिसका अर्थ है j के स्थान पर, में -len(a)-1 (या -(len(a)+1)) का उपयोग करना चाहिए, टुकड़ा a के अंतिम तत्व पर शुरू होता है, len(a) तत्वों के लिए छोड़ दिया जाता है और फिर एक और तत्व छोड़ दिया है, समाप्त a से पहले स्लाइस में a[0] शामिल होता है।

इसलिए, a[:-1:-1] का अर्थ है "कदम आकार के साथ, की a (j == -1 के बाद से) पिछले तत्व के लिए a के अंत है, जो a[-1] है से जाना (के बाद से i अनिर्दिष्ट है और k नकारात्मक है), -1 "। i और j बराबर हैं - आप एक ही स्थान पर स्लाइसिंग शुरू करते हैं और रोकते हैं - इसलिए अभिव्यक्ति एक खाली सूची में मूल्यांकन करती है।

a[:-1] को उलट करने के लिए, आप a[-2::-1] का उपयोग कर सकते हैं। इस तरह, टुकड़ा अंतिम तत्व पर शुरू होता है, a[-2] (a[:-1] में a[-1] शामिल नहीं है) और a[0] तत्व "पहले" तत्व से पीछे चला जाता है, जिसका अर्थ है कि a[0] स्लाइस में शामिल है।

>>> a 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
>>> a[:-1] 
[0, 1, 2, 3, 4, 5, 6, 7, 8] 
>>> a[-2::-1] 
[8, 7, 6, 5, 4, 3, 2, 1, 0] 
+2

"' a [: - 1: -1] 'का अर्थ है कि आप शुरुआत (इंडेक्स 0) से शुरू कर रहे हैं और जब तक आप अंतिम तत्व (अनुक्रमणिका -1) हिट नहीं करते हैं तब तक पीछे की तरफ जा रहे हैं। " सच नहीं। [अनुक्रम संचालन के लिए दस्तावेज़ों] के तहत नोट # 5 देखें (https://docs.python.org/3/library/stdtypes.html#common-sequence- संचालन): स्लाइस में 'a [i: j: k] ', "अगर मैं या जे छोड़े गए हैं या कोई नहीं, तो वे" अंत "मान बन जाते हैं (जो अंत के के संकेत पर निर्भर करता है)।" यही कारण है कि 'एक [: 1: -1] 'अंतिम' लेन (ए) - 2' तत्व देता है, पहला तत्व नहीं; यह 'ए [लेन (ए) -1: 1: -1] के बराबर है। – ThisSuitIsBlackNot

+1

@ThisSuitIsBlackNot मुझे नहीं लगता कि यह वह कुंजी है जिसे मैं समझ नहीं पाया: "कौन सा अंत के हस्ताक्षर पर निर्भर करता है"। धन्यवाद! –

+0

@ThisSuitIsBlackNot, मैट: आप पूरी तरह से सही हैं, मुझे खेद है कि मुझे यह इतना गलत मिला। मैं गलत जानकारी निकाल दूंगा और इसे फिर से लिखूंगा। – Josh

6

जब आप टाइप [1, 2, 3, ...][1:4:1] यह [1, 2, 3, ...][slice(1, 4, 1)] के समान है। तो 1:4:1slice ऑब्जेक्ट के लिए शॉर्टेंड है। slice हस्ताक्षर slice(stop) या slice(start, stop[, step]) है और आप तर्क के लिए None का भी उपयोग कर सकते हैं।

:: -> slice(None, None, None) 
:4 -> slice(4) 
# and so on 

मान लीजिए कि हमारे पास [a: b: c] है।

  1. पहले c चेक किया गया है: सूचकांक के लिए नियम इस प्रकार होगी। डिफ़ॉल्ट +1 है, c का संकेत चरण की आगे या पिछड़ी दिशा इंगित करता है। c का पूर्ण मूल्य चरण आकार इंगित करता है।
  2. a से अधिक चेक किया गया है। जब c सकारात्मक या None है, तो a के लिए डिफ़ॉल्ट 0 है। जब c नकारात्मक है, a के लिए डिफ़ॉल्ट -1 है।
  3. अंत में b चेक किया गया है। जब c सकारात्मक या None है, तो b के लिए डिफ़ॉल्ट len है। cb के लिए नकारात्मक डिफ़ॉल्ट है -(len+1) है।

नोट 1: अजगर में विकृत स्लाइस शान से नियंत्रित किया जाता है:

  • सूचकांक कि बहुत बड़ी या बहुत छोटे len या 0 साथ बदल दिया है है।
  • निचले बाउंड की तुलना में ऊपरी बाउंड एक खाली सूची या स्ट्रिंग या जो कुछ भी (सकारात्मक c के लिए) देता है।

नोट 2: मोटे तौर पर, अजगर तत्वों को चुनता है, जबकि इस हालत (a < b) if (c > 0) else (a > b)True (हर कदम पर a += c अद्यतन करना) है। साथ ही, सभी नकारात्मक सूचकांक len - index के साथ प्रतिस्थापित किए गए हैं।

यदि आप इन नियमों और नोट्स को गठबंधन करते हैं तो यह समझ में आएगा कि आपको खाली सूची क्यों मिली है। Explain Python's slice notation:

In[1]: [1, 2, 3, 4, 5, 6][:-1:-1]  # `c` is negative so `a` is -1 and `b` is -1 
Out[1]: [] 

# it is the same as: 

In[2]: [1, 2, 3, 4, 5, 6][-1: -1: -1] # which will produce you an empty list 
Out[2]: [] 

वहाँ टुकड़ा अंकन के बारे में बहुत अच्छी चर्चा है: आपके मामले में!

1

slice कि में range के लिए इसी तरह काम करता है जब आप step तर्क एक ऋणात्मक संख्या बनाने, start और stop तर्क विपरीत दिशा में काम करते हैं।

>>> list(range(9, -1, -1)) == a[::-1] 
True 

कुछ उदाहरण में मदद मिल सकती है कि इस और अधिक स्पष्ट:

>>> a[6:2:-2] 
[6, 4] 
>>> a[0:None:1] == a[::] 
True 
>>> a[-1:None:-1] == a[::-1] 
True 
>>> a[-2:None:-1] == a[:-1][::-1] 
True 
4

मैं आम तौर पर यह उपयोगी एक range -object काट करने के लिए (इस python3 में ही संभव है लगता है - को Python2 में range का उत्पादन एक list और xrange कटा हुआ नहीं किया जा सकता) अगर मैं यह देखने के लिए जो सूचकांक एक दिया लंबाई की एक सूची के लिए उपयोग किया जाता है की जरूरत है:

>>> range(10)[::-1] 
range(9, -1, -1) 

>>> range(10)[:-1] 
range(0, 9) 

और आपके अंतिम मामले में:

>>> range(10)[:-1:-1] 
range(9, 9, -1) 

यह भी बताता है कि क्या हुआ। पहली अनुक्रमणिका 9 है, लेकिन 9 स्टॉप इंडेक्स 9 से कम नहीं है (ध्यान दें कि पाइथन में स्टॉप इंडेक्स को छोड़ दिया गया है) इसलिए यह कोई तत्व दिए बिना बंद हो जाता है।

ध्यान दें कि अनुक्रमण भी क्रमिक रूप से लागू किया जा सकता:

>>> list(range(10))[::-1][:-1] # first reverse then exclude last item. 
[9, 8, 7, 6, 5, 4, 3, 2, 1] 
>>> list(range(10))[:-1][::-1] # other way around 
[8, 7, 6, 5, 4, 3, 2, 1, 0] 
संबंधित मुद्दे