2009-11-09 9 views
7

मैं की तरह कुछ करना चाहता हूँ:पायथन: जटिल सूची comprehensions जहां एक वर (परीक्षण में टी के लिए टी [1] में एक्स के लिए एक्स) पर एक और निर्भर करता है

all = [ x for x in t[1] for t in tests ] 

परीक्षण लगता है:

[ ("foo",[a,b,c]), ("bar",[d,e,f]) ] 

तो मैं परिणाम

all = [a,b,c,d,e,f] 

मेरे कोड काम नहीं करता है, अजगर का कहना चाहते हैं:

UnboundLocalError: local variable 't' referenced before assignment 

क्या ऐसा करने का कोई आसान तरीका है?

all = [x for t in tests for x in t[1]] 
+0

मुझे आपके मामले में x के लिए x की आवश्यकता को समझ में नहीं आता है। परीक्षण में टी के लिए आप बस = [टी [1] का उपयोग क्यों नहीं करते हैं]? – luc

+0

'[टी [1] परीक्षण में टी के लिए] 'tuples की एक सूची वापस कर देगा। '[एक्स में टी के लिए एक्स में परीक्षण के लिए एक्स [1]]' एक फ्लैट सूची (इन tuples का concatenation) है। –

उत्तर

15

यह दूसरी तरह के आसपास काम करना चाहिए।

अपने अजगर खोल में import this की कोशिश करो और दूसरी पंक्ति पढ़ें: तो कम से कम एक टिप्पणी जोड़ने के

Explicit is better than implicit 

सूची comprehensions की कंपाउंडिंग के इस प्रकार के अजगर प्रोग्रामर का एक बहुत पहेली है समझाने के लिए है कि आप तार हटा रहे हैं और शेष सूची flattening।

सूची समझों का उपयोग करें जहां वे स्पष्ट और समझने में आसान हैं, और विशेष रूप से, जब वे मूर्ख हैं, तो उनका उपयोग करें, यानी आमतौर पर उपयोग किया जाता है क्योंकि वे कुछ व्यक्त करने के लिए सबसे कुशल या सुरुचिपूर्ण तरीका हैं।

result = [3*d.Count for d in data if d.Count > 4] 

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

+0

धन्यवाद, मुझे आश्चर्य है कि मैंने खुद का परीक्षण क्यों नहीं किया है। :) कई अलग-अलग तरीकों की कोशिश की है। – Albert

+15

मुझे लगता है कि कई 'सूची' समझों के लिए पाइथन की पसंद की पसंद एक गलती थी। मैं समझता हूं कि यह कथन के लिए नेस्टेड के उपयोग को दोहराने की कोशिश कर रहा है, लेकिन मुझे परिणाम अपठनीय पाते हैं और इससे बचने के लिए प्रवृत्त होते हैं। – bobince

+1

@ बॉबन्स +1 पूरी तरह से सहमत हो गया है, अगर इरादा इसे सामान्य 'के लिए सुसंगत रखने के लिए था, तो बेहतर तरीका होगा कि ब्लॉक को चारों ओर ब्रैकेट के साथ' [x in l: f (x)] ' ; लेकिन इस मामले में लूप चर के उपयोग और परिभाषा को ध्यान में रखते हुए और अधिक समझ में आता है। – fortran

5

संदेह होने पर, सूची comprehensions का उपयोग नहीं करते:

+0

मुझे आशा है कि मैं आपको गलत समझूंगा: * सूची समझ का उपयोग न करें *। ** ** सूची सूची का उपयोग करें, सामान्य संचालन (जैसे मानचित्र) इस तरह से बहुत स्पष्ट हैं ('[f (x) आइटम्स में x के लिए]')। – u0b34a0f6ae

+1

मैं आइटम में एक्स के लिए '[f, x)' [f (x) 'मानचित्र (एफ, आइटम)' को बहुत पसंद करता हूं। यह कई अन्य पायथन मुहावरे की तरह है - उदा। 'dict (ज़िप (कुंजी, मान)) '- उसमें जब आप इसे आंतरिक बनाते हैं, तो इसका उपयोग करके अनावश्यक संस्थाओं को हटाकर कोड को और अधिक पठनीय बनाता है। KISS की वकालत के लिए –

+0

+1 –

1

यह मुझे कम करने जैसा दिखता है। दुर्भाग्य से अजगर को कम करने के लिए किसी भी वाक्यात्मक चीनी प्रदान नहीं करता है, तो हम लैम्ब्डा का उपयोग करना होगा: [] का उपयोग कर एक प्रारंभिक मूल्य के रूप में,

reduce(lambda x, y: x+y[1], tests, []) 
2

यदि सब आप कर रहे हैं एक साथ कुछ सूचियां जोड़ने का है, योग builtin का प्रयास करें:

all = sum((t[1] for t in tests), [])