2014-09-04 4 views
6

मैंने हाल ही में एक नेस्टेड पायथन सूची को फ़्लैट करने का एक तरीका ढूंढ लिया, जैसे: [[1,2,3], [4,5,6]], इसमें: [1,2,3,4,5, 6]।एक पायथन सूची को फ़्लैट करने के लिए सूची समझ कैसे काम करती है?

Stackoverflow हमेशा की तरह मददगार था और मैं इस सरल सूची समझ के साथ a post पाया:

l = [[1,2,3],[4,5,6]] 
flattened_l = [item for sublist in l for item in sublist] 

मैंने सोचा था कि मैं समझ गया कि कैसे सूची comprehensions काम करते हैं, लेकिन जाहिरा तौर पर मैं सबसे मंद विचार नहीं मिला है।

exactly_the_same_as_l = [item for item in sublist for sublist in l] 

कोई व्याख्या कर सकते हैं कि कैसे अजगर इन बातों की व्याख्या: क्या मुझे सबसे ज्यादा पहेली है कि ऊपर समझ के अलावा, यह भी चलाता है (हालांकि यह एक ही परिणाम नहीं देता है) है? दूसरी मजबूती के आधार पर, मैं उम्मीद करता हूं कि अजगर इसे वापस सामने लाएगा, लेकिन स्पष्ट रूप से यह हमेशा मामला नहीं है। यदि यह था, पहली समझ में एक त्रुटि फेंकनी चाहिए, क्योंकि 'sublist' मौजूद नहीं है। मेरा दिमाग पूरी तरह से warped है, मदद करो!

+1

लूप के लिए सामान्य में बदलने का सबसे अच्छा तरीका है और यह देखने के लिए प्रिंट का उपयोग करें कि –

+6

दूसरी समझ केवल इसलिए काम करती है क्योंकि 'आइटम' और 'सब्लिस्ट' पहली समझ से अपने अंतिम मूल्य बनाए रखती है। इसे पहले चलाएं (या 'डेल आइटम; डेल sublist' तो यह करते हैं) और यह अपेक्षित के रूप में' NameError' देगा। यहां अजीबता पाइथन के स्कॉइंग नियमों में है, समझ में नहीं। –

+1

@MarkWhitfield केवल python2 में ... python3 सूची-समझ में genexps के रूप में व्यवहार करते हैं और बाहरी दायरे में चर को रिसाव नहीं करते हैं। – Bakuriu

उत्तर

4

आइए अपनी सूची समझ पर नज़र डालें, लेकिन सबसे पहले इसे आसानी से सूची समझ से शुरू करें।

l = [1,2,3,4,5] 
print [x for x in l] # prints [1, 2, 3, 4, 5] 

आप इस एक ही देख सकते हैं एक पाश के लिए बहुत तरह संरचित के रूप में: चलो एक दूसरे को देखते हैं

for x in l: 
    print x 

अब:

l = [1,2,3,4,5] 
a = [x for x in l if x % 2 == 0] 
print a # prints [2,4] 

इस तरह बिल्कुल समान है :

a = [] 
l = [1,2,3,4,5] 
for x in l: 
    if x % 2 == 0: 
     a.append(x) 
print a # prints [2,4] 

अब चलो लेते हैं आपके द्वारा प्रदान किए गए उदाहरणों पर एक नज़र डालें।

l = [[1,2,3],[4,5,6]] 
flattened_l = [item for sublist in l for item in sublist] 
print flattened_l # prints [1,2,3,4,5,6] 

सूची समझ के लिए पाश के लिए बाईं ओर सब से अधिक दूर से शुरू और में अपने तरीके से काम। चर, मद, इस मामले में, क्या से जोड़ दिया जाएगा।यह इस बराबर का उत्पादन करेगा: एक ही ज्ञान का उपयोग करते हुए पिछले एक

exactly_the_same_as_l = [item for item in sublist for sublist in l] 

के लिए अब

l = [[1,2,3],[4,5,6]] 
flattened_l = [] 
for sublist in l: 
    for item in sublist: 
     flattened_l.append(item) 

हम पाश के लिए एक बना सकते हैं और देखें कि यह कैसे behaveL हैं

for item in sublist: 
    for sublist in l: 
     exactly_the_same_as_l.append(item) 
अब

केवल उपर्युक्त कार्यों का कारण यह है कि जब flattened_l बनाया गया था, तो यह sublist भी बनाया गया था। यह एक चौंकाने वाला कारण है कि उसने एक त्रुटि क्यों नहीं फेंक दी। यदि आपने पहले flattened_l को परिभाषित किए बिना भाग लिया था, तो आपको NameError

2

लूप के लिए बाएं से दाएं का मूल्यांकन किया जाता है। किसी भी list comprehension पाश के लिए एक के रूप में फिर से लिखा जा सकता है, इस प्रकार है:

l = [[1,2,3],[4,5,6]] 
flattened_l = [] 
for sublist in l: 
    for item in sublist: 
     flattened_l.append(item) 

ऊपर एक सूची सपाट के लिए सही कोड है कि क्या आप एक सूची समझ के रूप में संक्षेप में यह लिखने के लिए चुनते हैं, या इस विस्तारित संस्करण में ।

आपके द्वारा लिखी गई दूसरी सूची समझ एक नेमररर बढ़ाएगी, क्योंकि 'सब्लिस्ट' अभी तक परिभाषित नहीं किया गया है। आप पाश के लिए एक के रूप में सूची समझ लिख कर यह देख सकते हैं:

l = [[1,2,3],[4,5,6]] 
flattened_l = [] 
for item in sublist: 
    for sublist in l: 
     flattened_l.append(item) 

एकमात्र कारण आप त्रुटि नहीं देखा था जब तुम भाग गया अपने कोड क्योंकि आपने पहले sublist परिभाषित था, जब आपकी पहली सूची में समझ को लागू करने गया था।

अधिक जानकारी के लिए, आप Guido's tutorial on list comprehensions देख सकते हैं।

0

नोट, निश्चित रूप से, समझ की तरह सूचियों की सूची (या अन्य पुनरावृत्तियों की सूची) केवल "फ़्लैट" होगी। इसके अलावा यदि आप इसे तारों की एक सूची पास करते हैं तो आप इसे वर्णों की सूची में "फ़्लैट" करेंगे।

इसे सार्थक तरीके से सामान्य करने के लिए आप पहले तारों (या बाइटियर) और अन्य प्रकार के अनुक्रमों (या अन्य इटेरबल्स) के बीच स्पष्ट रूप से अंतर करने में सक्षम होना चाहते हैं। का उपयोग करना है कि हम तो समतल करने के लिए कोई

def flatten(s): 
    '''Recursively flatten any sequence of objects 
    ''' 
    results = list() 
    if non_str_seq(s): 
     for each in s: 
      results.extend(flatten(each)) 
    else: 
     results.append(s) 
    return results 

शायद यह करने के लिए और अधिक सुरुचिपूर्ण तरीके हैं एक पुनरावर्ती समारोह का निर्माण कर सकते

import collections 
def non_str_seq(p): 
    '''p is putatively a sequence and not a string nor bytearray''' 
    return isinstance(p, collections.Iterable) and not (isinstance(p, str) or isinstance(p, bytearray)) 

: तो चलो एक साधारण समारोह के साथ शुरू करते हैं। लेकिन यह उन सभी पायथन के लिए काम करता है जो मुझे पता है। सरल वस्तुओं (संख्या, तार, कोई नहीं, यह सच है के उदाहरण, झूठी सभी सूची में लिपटे रहे हैं वापस लौटे शब्दकोश कुंजी की सूची (हैश क्रम में) के रूप में वापस कर रहे हैं

1

आलसी देव है कि एक त्वरित जवाब चाहता है के लिए:।।

>>> a = [[1,2], [3,4]] 
>>> [i for g in a for i in g] 
[1, 2, 3, 4] 
संबंधित मुद्दे