एक छोटी अजगर सूची में शामिल होने के लिए मुहावरेदार वाक्यविन्यास क्या है?


542

list.append()एक सूची के अंत में जोड़ने के लिए स्पष्ट विकल्प है। यहां लापता के लिए एक उचित स्पष्टीकरण है list.prepend()। यह मानते हुए कि मेरी सूची छोटी है और प्रदर्शन की चिंताएं नगण्य हैं, है

list.insert(0, x)

या

list[0:0] = [x]

मुहावरेदार?

जवाबों:


782

s.insert(0, x)प्रपत्र सबसे आम है।

जब भी आप इसे देखते हैं, यह एक सूची के बजाय एक संग्रह का उपयोग करने पर विचार करने का समय हो सकता है ।


9
"जब भी आप इसे देखते हैं, तो यह एक सूची के बजाय एक संग्रह का उपयोग करने पर विचार करने का समय हो सकता है।" ऐसा क्यों है?
मैट एम।

6
@MattM। यदि आप किसी सूची के सामने रखते हैं, तो अजगर को अन्य सभी वस्तुओं को एक स्थान पर आगे बढ़ाना होगा, सूची "सामने की ओर स्थान नहीं बना सकती"। collection.deque (डबल एंडेड कतार) में "सामने की ओर जगह बनाने" के लिए समर्थन है और इस मामले में बहुत तेज है।
fejfo

265

यदि आप कार्यात्मक तरीके से जा सकते हैं, तो निम्नलिखित बहुत स्पष्ट है

new_list = [x] + your_list

बेशक, आपने इसमें सम्मिलित नहीं xकिया है your_list, बल्कि आपने इसके लिए एक नई सूची बनाई xहै।


45
जैसा कि आप निरीक्षण करते हैं, वह सूची में शामिल नहीं है। यह एक नई सूची बना रहा है। इस प्रकार यह सवाल को पूरा नहीं करता है।
क्रिस मॉर्गन

111
हालांकि यह प्रश्न को पूरा नहीं करता है, यह इसे पूरा करता है, और यही इस वेबसाइट का उद्देश्य है। टिप्पणी की सराहना करें और आप सही हैं, लेकिन जब लोग इसके लिए खोज करते हैं, तो यह देखना उपयोगी है।
dave4jr

2
इसके अलावा, यदि आप किसी सूची में किसी सूची को प्रस्तुत करना चाहते हैं तो सम्मिलित रूप से अपेक्षित रूप से काम नहीं करेगा। लेकिन यह विधि करता है!
gota

89

एक छोटी अजगर सूची में शामिल होने के लिए मुहावरेदार वाक्यविन्यास क्या है?

आप आमतौर पर पाइथन की सूची में दोहराव नहीं चाहते हैं।

यदि यह छोटा है , और आप इसे बहुत अधिक नहीं कर रहे हैं ... तो ठीक है।

list.insert

list.insertइस तरह से इस्तेमाल किया जा सकता।

list.insert(0, x)

लेकिन यह अक्षम्य है, क्योंकि पायथन में, एक व्यूअर listका एक सरणी है, और पायथन को अब सूची में प्रत्येक पॉइंटर को लेना चाहिए और पहले स्लॉट में अपनी ऑब्जेक्ट में पॉइंटर डालने के लिए इसे एक से नीचे ले जाना चाहिए, इसलिए यह वास्तव में केवल कुशल है छोटी सूचियों के लिए, जैसा कि आप पूछते हैं।

यहां CPython स्रोत से एक स्निपेट दिया गया है जहां इसे लागू किया गया है - और जैसा कि आप देख सकते हैं, हम सरणी के अंत में शुरू करते हैं और हर प्रविष्टि के लिए एक-एक करके सब कुछ नीचे ले जाते हैं:

for (i = n; --i >= where; )
    items[i+1] = items[i];

यदि आप एक कंटेनर / सूची चाहते हैं, जो पहले से मौजूद तत्वों में कुशल हो, तो आप एक लिंक की गई सूची चाहते हैं। पायथन की एक दोहरी लिंक वाली सूची है, जो शुरुआत और अंत में जल्दी से सम्मिलित कर सकता है - इसे ए कहा जाता है deque

deque.appendleft

A के collections.dequeपास सूची के कई तरीके हैं। list.sortएक अपवाद है, dequeनिश्चित रूप से पूरी तरह से Liskov के लिए स्थानापन्न नहीं है list

>>> set(dir(list)) - set(dir(deque))
{'sort'}

dequeयह भी एक है appendleftविधि (और साथ ही popleft)। dequeएक डबल समाप्त हो गया है और एक कतार दोगुना से जुड़े सूची है - कोई बात नहीं की लंबाई, यह हमेशा preprend कुछ करने के लिए समय की एक ही राशि लेता है। सूचियों के लिए बड़े O संकेतन में, O (1) बनाम O (n) समय। यहाँ उपयोग है:

>>> import collections
>>> d = collections.deque('1234')
>>> d
deque(['1', '2', '3', '4'])
>>> d.appendleft('0')
>>> d
deque(['0', '1', '2', '3', '4'])

deque.extendleft

इसके अलावा प्रासंगिक deque की extendleftविधि है, जो इसमें पूर्ववर्ती है :

>>> from collections import deque
>>> d2 = deque('def')
>>> d2.extendleft('cba')
>>> d2
deque(['a', 'b', 'c', 'd', 'e', 'f'])

ध्यान दें कि प्रत्येक तत्व को एक समय में एक पूर्व निर्धारित किया जाएगा, इस प्रकार उनके आदेश को प्रभावी ढंग से उलट दिया जाएगा।

listबनाम का प्रदर्शनdeque

पहले हम कुछ पुनरावृत्तियों के साथ सेटअप करते हैं:

import timeit
from collections import deque

def list_insert_0():
    l = []
    for i in range(20):
        l.insert(0, i)

def list_slice_insert():
    l = []
    for i in range(20):
        l[:0] = [i]      # semantically same as list.insert(0, i)

def list_add():
    l = []
    for i in range(20):
        l = [i] + l      # caveat: new list each time

def deque_appendleft():
    d = deque()
    for i in range(20):
        d.appendleft(i)  # semantically same as list.insert(0, i)

def deque_extendleft():
    d = deque()
    d.extendleft(range(20)) # semantically same as deque_appendleft above

और प्रदर्शन:

>>> min(timeit.repeat(list_insert_0))
2.8267281929729506
>>> min(timeit.repeat(list_slice_insert))
2.5210217320127413
>>> min(timeit.repeat(list_add))
2.0641671380144544
>>> min(timeit.repeat(deque_appendleft))
1.5863927800091915
>>> min(timeit.repeat(deque_extendleft))
0.5352169770048931

छल बहुत तेज है। जैसे-जैसे सूचियाँ लम्बी होंगी, मैं एक अच्छे प्रदर्शन की उम्मीद करूँगा। यदि आप deque का उपयोग कर सकते हैं, extendleftतो संभवतः आपको इस तरह का सर्वश्रेष्ठ प्रदर्शन मिलेगा।


57

अगर किसी को मेरी तरह यह सवाल लगता है, तो यहां प्रस्तावित विधियों के प्रदर्शन परीक्षण हैं:

Python 2.7.8

In [1]: %timeit ([1]*1000000).insert(0, 0)
100 loops, best of 3: 4.62 ms per loop

In [2]: %timeit ([1]*1000000)[0:0] = [0]
100 loops, best of 3: 4.55 ms per loop

In [3]: %timeit [0] + [1]*1000000
100 loops, best of 3: 8.04 ms per loop

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


11
एक चीज जो उस परीक्षण से गायब है वह जटिलता है। जबकि पहले दो विकल्पों में निरंतर जटिलता होती है (सूची में अधिक तत्व होने पर यह धीमा नहीं होता है), तीसरे में रैखिक जटिलता है (यह धीमी हो जाती है, सूची में तत्वों की मात्रा के आधार पर), क्योंकि यह हमेशा पूरी सूची को कॉपी करना है। सूची में अधिक तत्वों के साथ, परिणाम बहुत खराब हो सकता है।
डकारन

6
@Dakkaron मुझे लगता है कि आप इसके बारे में गलत हैं। कुछ स्रोतों को सूचीबद्ध करें। सूची के लिए रैखिक जटिलता का उल्लेख करें। उदाहरण के लिए, यह अच्छी तालिका है , और इससे जुड़े प्रश्नकर्ता को उचित स्पष्टीकरण से निहित है। मुझे संदेह है कि सीपीथॉन पहले दो मामलों में सूची में स्मृति में प्रत्येक तत्व को फिर से आवंटित कर रहा है, इसलिए इन तीनों में शायद रैखिक जटिलता है। मैंने वास्तव में कोड को नहीं देखा है या इसे स्वयं परीक्षण किया है, लेकिन यदि वे स्रोत गलत हैं तो क्षमा करें। Collections.deque.appendleft में आप जिस रैखिक जटिलता की बात कर रहे हैं।
टीसी प्रॉक्टर

@ डकारोन सच नहीं है, इन सभी में समान जटिलता है। यद्यपि .insertऔर जगह में[0:0] = [0] काम करते हैं , फिर भी उन्हें पूरे बफर को फिर से आवंटित करना होगा।
juanpa.arrivillaga

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