पायथन में सूचियों के लिए "समतल" फ़ंक्शन क्यों नहीं है?


39

एरलांग और रूबी दोनों चपटे सरणियों के लिए कार्य करते हैं। यह एक भाषा को जोड़ने के लिए इस तरह के एक सरल और उपयोगी उपकरण की तरह लगता है। कोई ऐसा कर सकता है:

>>> mess = [[1, [2]], 3, [[[4, 5]], 6]]
>>> mess.flatten()
[1, 2, 3, 4, 5, 6]

या और भी:

>>> import itertools
>>> mess = [[1, [2]], 3, [[[4, 5]], 6]]
>>> list(itertools.flatten(mess))
[1, 2, 3, 4, 5, 6]

इसके बजाय, पायथन में, किसी को खरोंच से चपटे सरणियों के लिए एक फ़ंक्शन लिखने की परेशानी से गुजरना पड़ता है। यह मुझे मूर्खतापूर्ण लगता है, चपटे सरणियाँ ऐसा करना एक सामान्य बात है। यह दो सरणियों को संक्षिप्त करने के लिए एक कस्टम फ़ंक्शन लिखने जैसा है।

मैंने इस फल को बेकार कर दिया है, इसलिए मैं यहां पूछ रहा हूं; क्या एक विशेष कारण है कि पायथन 3 जैसी एक परिपक्व भाषा, जिसमें एक सौ हजार विभिन्न बैटरी शामिल हैं, चपटे सरणियों का एक सरल तरीका प्रदान नहीं करता है? क्या इस तरह के समारोह को शामिल करने के विचार को किसी बिंदु पर चर्चा और खारिज कर दिया गया है?


2
@detly: विभिन्न स्रोतों से डेटा पुनः प्राप्त करने के लिए कई प्रश्नों का उपयोग करते समय मैं हाल ही में समतल याद करने के लिए हुआ। प्रत्येक क्वेरी शब्दकोशों की एक सूची देती है, इसलिए अंत में मेरे पास शब्दकोशों की सूचियों की एक सूची होती है, जिन्हें शब्दकोशों की सूची में बदल दिया जाता है। मैंने एक लूप का उपयोग किया + extendलेकिन समतल अधिक सुरुचिपूर्ण था। हालाँकि, मैं घाव करता हूँ यदि यह पैटर्न मानक पुस्तकालय में समतल होने के औचित्य के लिए पर्याप्त है।
जियोर्जियो

4
"मेरा मतलब है, कल्पना करें कि क्या आप अपने कोड में बग का परिचय देते हैं जो अनजाने में आपके डेटा की संरचना को बदल देता है। चपटा अभी भी काम करेगा, लेकिन पूरी तरह से गलत परिणाम उत्पन्न करता है।": यह एक कारण है कि मुझे सांख्यिकीय रूप से टाइप की जाने वाली भाषाएं पसंद हैं। ;-)
जियोर्जियो


2
@BryanOakley पूर्व टिप्पणी देखें (हालांकि बहु-स्तरीय सूचियों के लिए नहीं, सामान्य रूप से चपटे आम हैं)
इज़काता

3
यह Mathemaica में बनाया गया है, और मैं इसका बड़े पैमाने पर उपयोग करता हूं।
प्रति

जवाबों:


34

एक flattenसमारोह के लिए मानक पुस्तकालय में जोड़े जाने के प्रस्ताव समय - समय पर अजगर-देव और अजगर-विचार मेलिंग सूचियों पर दिखाई देते हैं । पायथन डेवलपर्स आमतौर पर निम्नलिखित बिंदुओं के साथ प्रतिक्रिया करते हैं:

  1. एक-स्तरीय समतल (एक पुनरावृति में पुनरावृत्तियों को एक एकल पुनरावृत्ति में बदलना) एक तुच्छ एक-पंक्ति अभिव्यक्ति है (x for y in z for x in y)और किसी भी मामले में नाम के तहत मानक पुस्तकालय में पहले से ही है itertools.chain.from_iterable

  2. एक सामान्य-उद्देश्य बहु-स्तरीय समतल के लिए उपयोग के मामले क्या हैं? क्या ये वास्तव में मानक लाइब्रेरी में जोड़े जाने वाले फ़ंक्शन के लिए पर्याप्त सम्मोहक हैं?

  3. एक सामान्य-उद्देश्य बहु-स्तरीय समतल कैसे तय करेगा कि कब समतल करना है और कब अकेला छोड़ना है? आप सोच सकते हैं कि "नियम कुछ भी जो चंचल इंटरफ़ेस का समर्थन करता है" को समतल कर देगा, लेकिन यह एक अनंत लूप को जन्म देगा flatten('a')

उदाहरण के लिए देखें रेमंड हैटिंगर :

यह comp.lang.python पर विज्ञापन nauseam पर चर्चा की गई है । लोगों को लगता है कि पहले से ही तुच्छ समाधान नहीं है वैध उपयोग के मामलों को खोजने से अधिक अपने स्वयं के संस्करणों को लिखने का आनंद लेने के लिए लगता है।

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


बस स्पष्ट होने के लिए, इसका मतलब है कि एक-स्तरीय flattenफ़ंक्शन को परिभाषित किया जा सकता है lambda z: [x for y in z for x in y]
क्रिस्टोफर मार्टिन

1
एक समस्या यह है कि OOP का उपयोग कर हल किया जा सकता है जैसे यह लगता है:: "एक सामान्य प्रयोजन flattener किसी तरह क्या परमाणु है और आगे क्या विभाजित किया जा सकता को बताया जाना चाहिए।" प्रत्येक वस्तु एक हो सकता था flattenविधि। इस विधि के कार्यान्वयन को पुन: flattenइसके उपसंपादक पर कॉल करना चाहिए , यदि ऑब्जेक्ट एक समग्र है। दुर्भाग्य से, AFAIK हर मूल्य पायथन में एक वस्तु नहीं है। रूबी में हालांकि यह काम करना चाहिए।
जियोर्जियो

1
एक के लिए एक समतल समतल के लिए एक समतल सहायक के बजाय एक "जारी" के लिए एक अच्छा पर्याप्त मामला IMO है। आसानी से पठनीय
dtc

2
@ जॉर्जियो पायथन ऐसे तरीकों से दूर भागते हैं। प्रोटोकॉल पसंद किए जाते हैं, और मुझे लगता है कि वे एक OOP डिजाइन के साथ काम करने के लिए बहुत चिकनी हैं क्योंकि आपको अक्सर बहुत अधिक लागू करने की आवश्यकता नहीं होती है।
jpmc26

8

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

[[1], [2, 3], [3, 4, 5]] #yes
[1, 2, [5, 6]] #no

एक समय में कंपाइलर.स्ट मॉड्यूल में एक समतल विधि थी, लेकिन इसे 2.6 में पदावनत किया गया और फिर 3.0 में हटा दिया गया। मनमाने ढंग से नेस्टेड सूचियों के लिए आवश्यक महत्वाकांक्षी गहराई की पुनरावृत्ति, पायथन की रूढ़िवादी अधिकतम पुनरावर्ती गहराई के साथ अच्छी तरह से काम नहीं करती है। कंपाइलर को हटाने का तर्क काफी हद तक गड़बड़ होने के कारण था । संकलक में बदल गया था ast लेकिन समतल पीछे छोड़ दिया गया था।

सुन्न की सरणियों और उस पुस्तकालय के समतल के साथ मनमाना गहराई प्राप्त की जा सकती है।


chain.from_iteratorसमारोह, जैसा कि आप ने कहा, केवल दो आयामी सूचियों समतल किया जा सकता है। एक वास्तविक समतल फ़ंक्शन, जो किसी भी मात्रा में नेस्टेड सूचियों को स्वीकार करता है और एक-आयामी सूची देता है, फिर भी बहुत सारे मामलों में बड़े पैमाने पर उपयोगी होगा (कम से कम मेरी राय में)
हुब्रो

2
@ हुब्रो: "बहुत सारे मामलों में" - क्या आप छह नाम रख सकते हैं?
गारेथ रीस

1
@GarethRees: मैंने यहाँ कुछ उदाहरण दिए: programmers.stackexchange.com/questions/254279/…
हब्रो

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

क्या यह एक पुनरावृत्ति या एक जनरेटर लौटाता है?
jpmc26

-1

... शायद इसलिए कि खुद लिखना मुश्किल नहीं है

def flatten(l): return flatten(l[0]) + (flatten(l[1:]) if len(l) > 1 else []) if type(l) is list else [l]

... और फिर आप चाहते हैं सभी समतल :)

>>> flatten([1,[2,3],4])
[1, 2, 3, 4]
>>> flatten([1, [2, 3], 4, [5, [6, {'name': 'some_name', 'age':30}, 7]], [8, 9, [10, [11, [12, [13, {'some', 'set'}, 14, [15, 'some_string'], 16], 17, 18], 19], 20], 21, 22, [23, 24], 25], 26, 27, 28, 29, 30])
[1, 2, 3, 4, 5, 6, {'age': 30, 'name': 'some_name'}, 7, 8, 9, 10, 11, 12, 13, set(['set', 'some']), 14, 15, 'some_string', 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
>>> 

8
पूछने वाले को इसके बारे में पता है: "पायथन में, किसी को खरोंच के बाद चपटे सरणियों के लिए एक फ़ंक्शन लिखने की परेशानी से गुजरना पड़ता है"। यह पूछे गए प्रश्न को संबोधित करने का प्रयास भी नहीं करता है, "यह मुझे मूर्खतापूर्ण लगता है, चपटे सरणियाँ ऐसा करना एक सामान्य बात है। यह दो सरणियों को समेटने के लिए एक कस्टम फ़ंक्शन लिखने जैसा है।"
gnat

1
विषय से बाहर ... लेकिन सुपर कूल :-) !!
सेफ़

यह उत्तर ओपी को यह बताने जैसा है कि वह एक अच्छा डेवलपर नहीं है क्योंकि वह नहीं जानता था कि फ़ंक्शन को स्वयं कैसे कोड किया जाए। मेरा सुझाव है कि आप अपने उत्तर की शुरुआत को संशोधित करें क्योंकि यह उन लोगों के लिए उपयोगी कोड है जो प्रश्न पर ठोकर खाते हैं, भले ही ऑफ-टॉपिक
फेडेरिको बोनाली
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.