2013-01-16 23 views
7

में चयनित एक सूची में तत्वों की जगह मैं एक सूची है: mylist = [0, 0, 0, 0, 0]अजगर

मैं केवल चयनित तत्वों बदलना चाहते हैं, का कहना है कि प्रथम, द्वितीय, और एक आम संख्या, A = 100 द्वारा चौथा।

एक तरह से यह करने के लिए:

mylist[:2] = [A]*2 
mylist[3] = A 
mylist 
[100, 100, 0, 100, 0] 

मैं एक एक लाइनर, या यह करने के लिए एक आसान विधि के लिए देख रहा हूँ। एक अधिक सामान्य और लचीला उत्तर बेहतर है।

+0

यह कैसे के बारे में? मेरी सूची [: 2], मेरी सूची [3] = [ए] * 2, ए –

उत्तर

7

खासकर जब से तुम का एक बड़ा हिस्सा बदल रहे हैं list, मैं इस अपरिवर्तनीय करना चाहते हैं:

mylist = [100 if i in (0, 1, 3) else e for i, e in enumerate(mylist)] 

यह अजगर में जानबूझकर है कि एक नए list बनाने एक एक लाइनर है, जबकि एकपरिवर्तनशीलके लिए एक स्पष्ट लूप की आवश्यकता है। आमतौर पर, यदि आप नहीं जानते कि आप कौन सी चाहते हैं, तो आप नया list चाहते हैं। (कुछ मामलों में यह धीमा या अधिक जटिल है, या आपके पास कुछ अन्य कोड है जिसमें list का संदर्भ है और इसे उत्परिवर्तित, या जो भी हो, उसे देखने की आवश्यकता है, यही कारण है कि यह "हमेशा" के बजाय "आमतौर पर" होता है।)

आप एक बार की तुलना में इस अधिक करने के लिए चाहते हैं, तो मैं इसे एक समारोह में, लपेट था अस्थिरता के रूप में पता चलता है:

def elements_replaced(lst, new_element, indices): 
    return [new_element if i in indices else e for i, e in enumerate(lst)] 

मैं व्यक्तिगत रूप से शायद यह एक जनरेटर होगा तो यह बजाय एक यात्रा पैदावार एक सूची लौटाना, भले ही मुझे इसकी आवश्यकता नहीं होगी, सिर्फ इसलिए कि मैं उस तरह से बेवकूफ हूं। लेकिन यह जरूरत है कि आप वास्तव में करना:

myiter = (100 if i in (0, 1, 3) else e for i, e in enumerate(mylist)) 

या:

def elements_replaced(lst, new_element, indices): 
    for i, e in enumerate(lst): 
     if i in indices: 
      yield new_element 
     else: 
      yield e 
+0

नई सूची और उत्परिवर्तन के बारे में अच्छी व्याख्या। – elwc

+0

कभी-कभी मुझे 'valarray :: gslice' – Abhijit

+0

@ अभिजीत याद आती है: ठीक है, लगभग हर मामले जहां' वालर्रे 'सी ++ में समझ में आता है,' numpy' पायथन में समझ में आता है- और 'numpy' की विस्तारित स्लाइसिंग भी सरल है लगभग सभी मामलों के लिए 'gslice'। उदाहरण के लिए, इस सवाल के लिए mgilson का जवाब देखें। (बेशक "लगभग हर" और "लगभग सभी" बिल्कुल "हर" और "सभी" के समान नहीं हैं ... लेकिन यह दुर्लभ है कि मैं खुद को कुछ 'numpy' कोड लिख रहा हूं और एक सी ++ सुविधा खो रहा हूं ...) – abarnert

0

क्या आप यह देख रहे हैं? उन इंडेक्स की एक सूची बनाएं जिन्हें आप बदलना चाहते हैं, और फिर मानों को बदलने के लिए उस सूची के माध्यम से लूप करें।

els_to_replace = [0, 1, 3] 

mylist = [0, 0, 0, 0, 0] 

for index in els_to_replace: 
    mylist[index] = 100 


mylist 
Out[9]: [100, 100, 0, 100, 0] 
2
def replace_element(lst, new_element, indices): 
    for i in indices: 
     lst[i] = new_element 
    return lst 

यह निश्चित रूप से एक अधिक सामान्य समाधान, नहीं एक एक लाइनर हालांकि है। उदाहरण के लिए, आपके मामले में, आप कहेंगे:

mylist = replace_element(mylist, 100, [0, 1, 3]) 
+0

+1। अधिक सामान्य होने के शीर्ष पर, मुझे लगता है कि यह एक-लाइनर नहीं होने के बावजूद (या, बल्कि, शायद) के बावजूद म्यूटेबल प्रतिस्थापन करने का सबसे पठनीय तरीका है। – abarnert

1

Numpy इस का समर्थन करता है अगर आप एक np.ndarray का उपयोग कर के लिए विरोध नहीं कर रहे हैं:

>>> a = np.zeros(5) 
>>> a[[0,1,3]] = 100 
>>> a 
array([ 100., 100., 0., 100., 0.]) 
+0

+1। भले ही यह सीधे ओपी के प्रश्न का उत्तर नहीं देता है (और मुझे यकीन नहीं है कि यह नहीं है), जब भी आप खुद को संख्याओं के अनुक्रमों से निपटते हैं और कुछ ऐसा लगता है उससे कठिन लगता है, तो आपको पहले सवाल पूछना चाहिए "क्या मैं यहां 'एनपी.न्डार्रे' का उपयोग करने का विरोध कर रहा हूं?" – abarnert

0

नहीं यह एक की बहुत बड़ी प्रशंसक हैं, लेकिन आप यह कोशिश कर सकते हैं (हालांकि मुझे लगता है कि ऊपर के सभी और अधिक कर रहे हैं संक्षिप्त और आसान को पढ़ने के लिए): संदिग्ध पठनीयता के अलावा

In [22]: from operator import setitem 

In [23]: mylist = [0, 0, 0, 0, 0] 

In [24]: indeces_to_replace = [0, 1, 3] 

In [25]: _ = map(lambda x: setitem(mylist, x, 100), indeces_to_replace) 

In [26]: mylist 
Out[26]: [100, 100, 0, 100, 0] 

और एक आयात के लिए की जरूरत है, @abarnert कुछ अतिरिक्त मुद्दों ने बताया, अर्थात् है कि 012,369,अभी भी एक अनावश्यक सूची बनाता है (जिसे _ से हटा दिया गया है लेकिन फिर भी बनाया गया है) और यह पाइथन 3 में काम नहीं करेगा क्योंकि mapreturns an iterator पायथन 3.x में। आप पाइथन 2 से पायथन 3.x में map के व्यवहार को अनुकरण करने के लिए six मॉड्यूल का उपयोग कर सकते हैं।एक्स, और collections.deque (फिर से @abarnert द्वारा सुझाए गए अनुसार) के संयोजन में, आप स्मृति में अतिरिक्त सूची बनाये बिना एक ही आउटपुट प्राप्त कर सकते हैं क्योंकि deque जिसमें अधिकतम 0 आइटम शामिल हो सकते हैं, यह map इटेटर (ध्यान दें कि six के साथ, mapitertools.imap का उपयोग कर अनुकरण किया गया है)।

फिर, बिल्कुल नहीं कभी भी इस का उपयोग करने की आवश्यकता है -/नीचे से ऊपर हर समाधान :)

In [1]: from collections import deque 

In [2]: from six.moves import map 

In [3]: from operator import setitem 

In [4]: mylist = [0, 0, 0, 0, 0] 

In [5]: indeces_to_replace = [0, 1, 3] 

In [6]: deque(map(lambda x: setitem(mylist, x, 100), indeces_to_replace), maxlen=0) 
Out[6]: deque([], maxlen=0) 

In [7]: mylist 
Out[7]: [100, 100, 0, 100, 0] 
+0

मुख्य इसके साथ समस्या यह है कि पायथन 3 में, यह काम नहीं करता है, क्योंकि आप केवल एक पुनरावर्तक वापस लेते हैं जिसे आप कभी भी पुन: सक्रिय नहीं करते हैं। कम समस्या यह है कि पायथन 2 में, यह ऐसी सूची बनाता है जिसकी आपको आवश्यकता नहीं है। आप 'सूची (मानचित्र (...)) स्पष्ट रूप से कर कर पहली समस्या को हल कर सकते हैं। या आप 'six.map' का उपयोग कर दोनों को हल कर सकते हैं और परिणाम को 'iter_discard' फ़ंक्शन पर पास कर सकते हैं, जिसे आप' collections.deque (it, max_size = 0)' के रूप में कार्यान्वित कर सकते हैं। जो भी आपको एक समाधान में डालने की तुलना में एक बहुत अधिक विचार है, आप निश्चित रूप से पहले स्थान पर एक बड़ा प्रशंसक नहीं थे ... – abarnert

+0

@abarnert आपके उत्तर में +1 +1 (हमेशा के रूप में जानकारीपूर्ण), और महान अंक इस कार्यान्वयन के संबंध में ('iter_discard' फ़ंक्शन 'के परिणामों को पास करने के बारे में कभी नहीं सोचा था। मैं पोस्टरिटी के लिए एक अपडेट में जोड़ूंगा, और उपयोगी जानकारी के लिए हमेशा धन्यवाद :) – RocketDonkey

+0

मैं वास्तव में चाहता हूं कि 'iter_discard' 3.x मानक लाइब्रेरी का हिस्सा था। इसके खिलाफ तर्क यह था कि यह परिणामों के बजाए साइड इफेक्ट्स के लिए 'मानचित्र' का उपयोग करके लोगों को प्रोत्साहित करना चाहता है (और, यदि आप वास्तव में इसे चाहते हैं, तो 'डेक' चाल को 'itertools' के लिए दस्तावेज़ में जोड़ा गया है)। मैं इसे खरीद सकता हूं ... लेकिन इस तरह के प्रश्नों के लिए, लोग हमेशा वैसे भी करते हैं (और फिर पाइथन के प्रत्येक संस्करण के साथ परिणामों को 'समयबद्ध' करना चाहते हैं)। – abarnert

0

मैं एक सूची समझ चाहते बेहतर है:

[100 if index in [1, 4] else 0 for index, x in enumerate(mylist) ]