सवाल पायथन में सूचियों की सूची से एक फ्लैट सूची बनाना


मुझे आश्चर्य है कि पाइथन में सूचियों की सूची से एक साधारण सूची बनाने के लिए शॉर्टकट है या नहीं।

मैं इसे लूप में कर सकता हूं, लेकिन हो सकता है कि कुछ ठंडा "एक-लाइनर" हो? मैंने इसके साथ कोशिश की को कम, लेकिन मुझे एक त्रुटि मिलती है।

कोड

l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
reduce(lambda x, y: x.extend(y), l)

त्रुटि संदेश

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <lambda>
AttributeError: 'NoneType' object has no attribute 'extend'

2083
2018-06-04 20:30


मूल


यहां इसकी गहराई से चर्चा की गई है: rightfootin.blogspot.com/2006/09/more-on-python-flatten.html, सूचियों की मनमाने ढंग से नेस्टेड सूचियों को फ़्लैटन करने के कई तरीकों पर चर्चा करते हुए। एक दिलचस्प पढ़ा! - RichieHindle
कुछ अन्य उत्तरों बेहतर हैं लेकिन आपका असफल होने का कारण यह है कि 'विस्तार' विधि हमेशा कोई नहीं लौटाती है। लंबाई 2 के साथ एक सूची के लिए, यह काम करेगा लेकिन कोई भी वापस नहीं। लंबी सूची के लिए, यह पहले 2 तर्कों का उपभोग करेगा, जो कोई भी नहीं लौटाता है। यह तब none.extend (<3rd arg>) के साथ जारी है, जो इस एरो का कारण बनता है - mehtunguh
@ शॉन-चिन समाधान यहां अधिक पाइथोनिक है, लेकिन यदि आपको अनुक्रम प्रकार को संरक्षित करने की आवश्यकता है, तो कहें कि सूचियों की सूची के बजाय आपके पास टुपल्स का टुपल है, तो आपको कम (ऑपरेटर.कोनकैट, tuple_of_tuples) का उपयोग करना चाहिए। Tuples के साथ operator.concat का उपयोग करना सूची के साथ chain.from_iterables से तेज प्रदर्शन करता प्रतीत होता है। - Meitham
numpy.array ([[1], [2]])। flatten ()। tolist (), जो आंतरिक संरचना को हटा देता है और सूची देता है [1,2] - user5920660
अब समर्थित है mpu: import mpu; mpu.datastructures.flatten([1, [2, 3], [4, [5, 6]]]) देता है [1, 2, 3, 4, 5, 6] - Martin Thoma


जवाब:


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

जिसका मतलब है:

for sublist in l:
    for item in sublist:
        flat_list.append(item)

अभी तक पोस्ट शॉर्टकट से तेज है। (l flatten की सूची है।)

यहां एक संबंधित कार्य है:

flatten = lambda l: [item for sublist in l for item in sublist]

साक्ष्य के लिए, हमेशा के रूप में, आप का उपयोग कर सकते हैं timeit मानक पुस्तकालय में मॉड्यूल:

$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]'
10000 loops, best of 3: 143 usec per loop
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 3: 969 usec per loop
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'reduce(lambda x,y: x+y,l)'
1000 loops, best of 3: 1.1 msec per loop

स्पष्टीकरण: शॉर्टकट पर आधारित है + (इसमें अंतर्निहित उपयोग सहित sum), आवश्यकता के हैं, O(L**2) जब एल sublists हैं - क्योंकि मध्यवर्ती परिणाम सूची लंबी हो रही है, प्रत्येक चरण में एक नई मध्यवर्ती परिणाम सूची वस्तु आवंटित हो जाती है, और पिछले मध्यवर्ती परिणाम में सभी वस्तुओं की प्रतिलिपि बनाई जानी चाहिए (साथ ही साथ कुछ नए जोड़े गए अतं मै)। तो (सादगी के लिए और सामान्यता के वास्तविक नुकसान के बिना) का कहना है कि आपके पास प्रत्येक आइटम के एल उपन्यास हैं: पहले आइटमों को एल-1 बार पीछे और पीछे कॉपी किया गया है, दूसरा मैं एल-2 बार आइटम करता हूं, और इसी तरह; प्रतियों की कुल संख्या मैं x के लिए एक्स के योग को 1 से एल तक छोड़ दिया गया है, यानी, I * (L**2)/2

सूची की समझ सिर्फ एक सूची उत्पन्न करती है, एक बार, और प्रत्येक आइटम को प्रतिस्थापित करता है (निवास की मूल स्थान से परिणाम सूची में) बिल्कुल एक बार।


3001
2018-06-04 20:37



मैंने प्रयोग करके, उसी डेटा के साथ एक परीक्षण की कोशिश की itertools.chain.from_iterable : $ python -mtimeit -s'from itertools import chain; l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'list(chain.from_iterable(l))'। यह नेस्टेड सूची समझ के रूप में दोगुनी से भी अधिक तेजी से चलता है जो यहां दिखाए गए विकल्पों में से सबसे तेज़ है। - intuited
मैंने सिंटैक्स को तब तक समझने में कठोर पाया जब तक मुझे एहसास नहीं हुआ कि आप इसके बारे में सोच सकते हैं जैसे लूप के लिए घोंसला। एल में sublist के लिए: sublist में आइटम के लिए: उपज आइटम - Rob Crowell
@ बोरीस चेर्नवेकोव: ध्यान दें कि मैंने कॉल को लपेट लिया है list() एक सूची में इटेटरेटर का एहसास करने के लिए। - intuited
[वृक्ष में पत्ते के लिए जंगल में पेड़ के लिए पत्ता] समझना और लागू करना आसान हो सकता है। - John Mee
@ जोएल, वास्तव में आजकल list(itertools.chain.from_iterable(l)) सबसे अच्छा है - जैसा कि अन्य टिप्पणियों और शॉन के जवाब में देखा गया है। - Alex Martelli


आप उपयोग कर सकते हैं itertools.chain():

>>> import itertools
>>> list2d = [[1,2,3],[4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain(*list2d))

या, पायथन> = 2.6 पर, उपयोग करें itertools.chain.from_iterable() जो सूची को अनपॅक करने की आवश्यकता नहीं है:

>>> import itertools
>>> list2d = [[1,2,3],[4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain.from_iterable(list2d))

यह दृष्टिकोण तर्कसंगत रूप से अधिक पठनीय है [item for sublist in l for item in sublist] और यह भी तेजी से प्रतीत होता है:

[me@home]$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99;import itertools' 'list(itertools.chain.from_iterable(l))'
10000 loops, best of 3: 24.2 usec per loop
[me@home]$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]'
10000 loops, best of 3: 45.2 usec per loop
[me@home]$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 3: 488 usec per loop
[me@home]$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'reduce(lambda x,y: x+y,l)'
1000 loops, best of 3: 522 usec per loop
[me@home]$ python --version
Python 2.7.3

1083
2018-06-04 21:06



@ShawnChin बीटीडब्लू, इस सवाल का जवाब देते समय आपके पास हार्डवेयर का टुकड़ा था, मेरा वर्तमान वर्कस्टेशन आधा तेज है और 4 साल हो गया है। - Manuel Gutierrez
@alexandre देखें docs.python.org/2/tutorial/... - Shawn Chin
* यह मुश्किल चीज है जो बनाता है chain सूची समझ से कम सरल। आपको यह जानना होगा कि श्रृंखला केवल पैरामीटर के रूप में पारित पुनरावृत्तियों को एक साथ जोड़ती है, और * शीर्ष-स्तरीय सूची को पैरामीटर में विस्तारित करने का कारण बनती है, इसलिए chain उन सभी पुनरावृत्तियों को एक साथ जोड़ता है, लेकिन आगे नहीं उतरता है। मुझे लगता है कि यह इस मामले में श्रृंखला के उपयोग की तुलना में समझ को और अधिक पठनीय बनाता है। - Tim Dierks
@TimDierks: मुझे यकीन नहीं है कि "आपको पाइथन सिंटैक्स को समझने की आवश्यकता है" पायथन में दी गई तकनीक का उपयोग करने के खिलाफ एक तर्क है। निश्चित रूप से, जटिल उपयोग भ्रमित हो सकता है, लेकिन "स्प्लट" ऑपरेटर आमतौर पर कई परिस्थितियों में उपयोगी होता है, और यह इसका उपयोग विशेष रूप से अस्पष्ट तरीके से नहीं कर रहा है; उन सभी भाषा सुविधाओं को अस्वीकार करना जो उपयोगकर्ताओं को शुरू करने के लिए जरूरी नहीं हैं, इसका मतलब है कि आप अपनी पीठ के पीछे एक हाथ बांध रहे हैं। जब भी आप इसमें हों, तब भी सूची समझें फेंक दें; अन्य पृष्ठभूमि के उपयोगकर्ताओं को एक मिल जाएगा for बार-बार लूप appendऔर अधिक स्पष्ट है। - ShadowRanger
किस बारे में ['abcde_', ['_abcde', ['e_abcd', ['de_abc', ['cde_ab', ['bcde_a']]]]]] - Aymon Fournier


लेखक से नोट करें: यह अक्षम है। लेकिन मजेदार, क्योंकि monads भयानक हैं। यह उत्पादन पायथन कोड के लिए उपयुक्त नहीं है।

>>> sum(l, [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]

यह केवल पहले तर्क में पारित होने वाले पुनरावृत्तियों के तत्वों को बताता है, दूसरे तर्क को योग के प्रारंभिक मूल्य के रूप में मानते हैं (यदि नहीं दिया गया है, 0 इसके बजाए प्रयोग किया जाता है और यह मामला आपको एक त्रुटि देगा)।

क्योंकि आप नेस्टेड सूचियों को जोड़ रहे हैं, आप वास्तव में मिलता है [1,3]+[2,4] के परिणाम स्वरूप sum([[1,3],[2,4]],[]), जो बराबर है [1,3,2,4]

ध्यान दें कि केवल सूचियों की सूचियों पर काम करता है। सूचियों की सूचियों की सूचियों के लिए, आपको एक और समाधान की आवश्यकता होगी।


638
2018-06-04 20:35



यह बहुत साफ और चालाक है लेकिन मैं इसका उपयोग नहीं करता क्योंकि यह पढ़ने में भ्रमित है। - andrewrk
यह चित्रकार के एल्गोरिदम श्लेमीएल है joelonsoftware.com/articles/fog0000000319.html - अनावश्यक रूप से अक्षम और साथ ही अनावश्यक बदसूरत। - Mike Graham
सूचियों पर परिचालन ऑपरेशन एक बनाता है Monoid, जो कि एक के बारे में सोचने के लिए सबसे सुविधाजनक abstractions में से एक है + एक सामान्य अर्थ में ऑपरेशन (केवल संख्या तक सीमित नहीं)। तो यह जवाब एक मोरॉयड के रूप में सूचियों के इलाज (सही) उपचार के लिए मेरे लिए एक +1 का हकदार है। प्रदर्शन हालांकि संबंधित है ... - ulidtko
@andrewrk ठीक है, कुछ लोग सोचते हैं कि यह करने का यह सबसे साफ तरीका है: youtube.com/watch?v=IOiZatlZtGU जो लोग नहीं पाते हैं कि यह क्यों ठंडा है, उन्हें कुछ दशकों तक इंतजार करने की ज़रूरत है जब तक कि हर कोई ऐसा नहीं करता है :) चलो प्रोग्रामिंग भाषाओं (और अवशोषण) का उपयोग करें जो खोजे जाते हैं और आविष्कार नहीं किए जाते हैं, मोनॉयड की खोज की जाती है। - jhegedus
यह योग के वर्गबद्ध पहलू की वजह से एक बहुत ही अक्षम तरीका है। - Jean-François Fabre


मैंने सबसे अधिक सुझाए गए समाधानों का परीक्षण किया perfplot (मेरा एक पालतू परियोजना, अनिवार्य रूप से एक रैपर चारों ओर timeit), और मिल गया

list(itertools.chain.from_iterable(a))

सबसे तेज़ समाधान होने के लिए (यदि 10 से अधिक सूचियों को समेकित किया गया है)।

enter image description here


साजिश को पुन: उत्पन्न करने के लिए कोड:

import functools
import itertools
import numpy
import operator
import perfplot


def forfor(a):
    return [item for sublist in a for item in sublist]


def sum_brackets(a):
    return sum(a, [])


def functools_reduce(a):
    return functools.reduce(operator.concat, a)


def itertools_chain(a):
    return list(itertools.chain.from_iterable(a))


def numpy_flat(a):
    return list(numpy.array(a).flat)


def numpy_concatenate(a):
    return list(numpy.concatenate(a))


perfplot.show(
    setup=lambda n: [list(range(10))] * n,
    kernels=[
        forfor, sum_brackets, functools_reduce, itertools_chain, numpy_flat,
        numpy_concatenate
        ],
    n_range=[2**k for k in range(16)],
    logx=True,
    logy=True,
    xlabel='num lists'
    )

131
2017-07-26 09:38





from functools import reduce #python 3

>>> l = [[1,2,3],[4,5,6], [7], [8,9]]
>>> reduce(lambda x,y: x+y,l)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

extend() आपके उदाहरण में विधि संशोधित करता है x एक उपयोगी मूल्य लौटने की बजाय (जो reduce() उम्मीद है)।

करने के लिए एक तेज तरीका है reduce संस्करण होगा

>>> import operator
>>> l = [[1,2,3],[4,5,6], [7], [8,9]]
>>> reduce(operator.concat, l)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

100
2018-06-04 20:35



reduce(operator.add, l) करने का सही तरीका होगा reduce संस्करण। बिल्टडास से निर्मित तेज हैं। - agf
@agf यहां है: * timeit.timeit('reduce(operator.add, l)', 'import operator; l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]', number=10000)  .017956018447875977   * timeit.timeit('reduce(lambda x, y: x+y, l)', 'import operator; l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]', number=10000)  .025218963623046875 - lukmdo
यह एक श्लेमीएल है जो चित्रकार के एल्गोरिदम joelonsoftware.com/articles/fog0000000319.html है - Mike Graham
यह केवल के लिए उपयोग कर सकते हैं integers। लेकिन अगर सूची में क्या है string? - Freddy
@ फ्र्रेडी: द operator.add फ़ंक्शन स्ट्रिंग्स की पूर्णांक और सूचियों की दोनों सूचियों के लिए समान रूप से अच्छी तरह से काम करता है। - Greg Hewgill


यहां एक सामान्य दृष्टिकोण है जो लागू होता है संख्या, तार, नेस्ट सूचियां और मिश्रित कंटेनर।

कोड

from collections import Iterable


def flatten(items):
    """Yield items from any nested iterable; see Reference."""
    for x in items:
        if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
            for sub_x in flatten(x):
                yield sub_x
        else:
            yield x

नोट: पायथन 3 में, yield from flatten(x) बदल सकते हैं for sub_x in flatten(x): yield sub_x

डेमो

lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(flatten(lst))                                         # nested lists
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

mixed = [[1, [2]], (3, 4, {5, 6}, 7), 8, "9"]              # numbers, strs, nested & mixed
list(flatten(mixed))
# [1, 2, 3, 4, 5, 6, 7, 8, '9']

संदर्भ

  • इस समाधान में एक नुस्खा से संशोधित किया गया है बेजले, डी। और बी जोन्स। पकाने की विधि 4.14, पायथन कुकबुक तीसरी एड।, ओ रेली मीडिया इंक सेबस्तोपोल, सीए: 2013।
  • पहले मिला एसओ पोस्ट, संभवतः मूल प्रदर्शन।

55
2017-11-29 04:14



मैंने अभी भी बहुत कुछ लिखा है, क्योंकि मैंने आपका समाधान नहीं देखा ... यहां मैंने जो "पूरी तरह से कई सूचियों को दोहराया" ... (+1) - Martin Thoma
@ मार्टिन थोमा बहुत सराहना की। एफवाईआई, अगर नेस्टेड इटरेबल्स फ़्लैटनिंग आपके लिए एक आम प्रथा है, तो कुछ तीसरे पक्ष के पैकेज हैं जो इसे अच्छी तरह से संभालते हैं। यह पहिया को पुनर्निर्मित करने से बचा सकता है। मैंने उल्लेख किया है more_itertools इस पोस्ट में चर्चा की गई अन्य लोगों के बीच। चीयर्स। - pylang
अच्छा - बस एक के बारे में सोच रहा था yield from सीखने के बाद पाइथन पर निर्माण का प्रकार yield * es2015 में। - Triptych
के द्वारा बदला गया if isinstance(el, collections.Iterable) and not isinstance(el, (str, bytes)): स्ट्रिंग का समर्थन करने के लिए। - Jorge Leitão
सही बात। मूल कुकबुक रेसिपी वास्तव में दिखाती है कि स्ट्रिंग्स और बाइट्स का समर्थन कैसे करें। अगर इस समर्थन को प्रतिबिंबित करने के लिए इसे संपादित किया गया है। - pylang


मैं अपना बयान वापस लेता हूं। योग विजेता नहीं है। हालांकि सूची तेज होने पर यह तेज़ है। लेकिन प्रदर्शन बड़ी सूचियों के साथ महत्वपूर्ण रूप से घटता है। 

>>> timeit.Timer(
        '[item for sublist in l for item in sublist]',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10000'
    ).timeit(100)
2.0440959930419922

योग संस्करण अभी भी एक मिनट से अधिक समय तक चल रहा है और अभी तक प्रसंस्करण नहीं किया है!

मध्यम सूचियों के लिए:

>>> timeit.Timer(
        '[item for sublist in l for item in sublist]',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10'
    ).timeit()
20.126545906066895
>>> timeit.Timer(
        'reduce(lambda x,y: x+y,l)',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10'
    ).timeit()
22.242258071899414
>>> timeit.Timer(
        'sum(l, [])',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10'
    ).timeit()
16.449732065200806

छोटी सूचियों और समय सारिणी का उपयोग करना: संख्या = 1000000

>>> timeit.Timer(
        '[item for sublist in l for item in sublist]',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]'
    ).timeit()
2.4598159790039062
>>> timeit.Timer(
        'reduce(lambda x,y: x+y,l)',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]'
    ).timeit()
1.5289170742034912
>>> timeit.Timer(
        'sum(l, [])',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]'
    ).timeit()
1.0598428249359131

31
2018-06-04 20:46



वास्तव में अल्पसंख्यक सूची के लिए, उदा। एक 3 उपन्यासकारों के साथ, शायद - लेकिन चूंकि योग का प्रदर्शन ओ (एन ** 2) के साथ जाता है, जबकि सूची की समझ ओ (एन) के साथ जाती है, केवल इनपुट सूची बढ़ती है, कुछ चीजें विपरीत होंगी - वास्तव में एलसी " एन बढ़ने के रूप में सीमा पर योग की तुलना में असीम तेज़ "। मैं पाइथन रनटाइम में योग बनाने और अपना पहला कार्यान्वयन करने के लिए ज़िम्मेदार था, और मुझे अभी भी इच्छा है कि मुझे इसे संख्याओं को संक्षेप में प्रतिबंधित करने का एक तरीका मिल गया है (यह वास्तव में क्या अच्छा है) और लोगों को यह "आकर्षक उपद्रव" को अवरुद्ध करता है जो सूचियों को "योग" करना चाहते हैं ;-)। - Alex Martelli


आप विस्तार का उपयोग क्यों करते हैं?

reduce(lambda x, y: x+y, l)

यह ठीक काम करना चाहिए।


25
2018-06-04 20:38



यह शायद कई, कई, मध्यवर्ती सूचियां बनाता है। - Reut Sharabani
पायथन 3 के लिए from functools import reduce - andorov
क्षमा करें कि वास्तव में बाकी जवाब देखें - Mr_and_Mrs_D


ऐसा लगता है कि एक भ्रम है operator.add! जब आप एक साथ दो सूचियां जोड़ते हैं, तो इसके लिए सही शब्द होता है concat, जोड़ें नहीं। operator.concat क्या आपको उपयोग करने की आवश्यकता है।

यदि आप कार्यात्मक सोच रहे हैं, तो यह उतना ही आसान है जितना ::

>>> list2d = ((1,2,3),(4,5,6), (7,), (8,9))
>>> reduce(operator.concat, list2d)
(1, 2, 3, 4, 5, 6, 7, 8, 9)

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

>>> list2d = [[1,2,3],[4,5,6], [7], [8,9]]
>>> reduce(operator.concat, list2d)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

आह, आप एक सूची वापस आते हैं।

प्रदर्शन के बारे में कैसे ::

>>> list2d = [[1,2,3],[4,5,6], [7], [8,9]]
>>> %timeit list(itertools.chain.from_iterable(list2d))
1000000 loops, best of 3: 1.36 µs per loop

से_iterable बहुत तेज़ है! लेकिन यह concat के साथ कम करने के लिए कोई तुलना नहीं है।

>>> list2d = ((1,2,3),(4,5,6), (7,), (8,9))
>>> %timeit reduce(operator.concat, list2d)
1000000 loops, best of 3: 492 ns per loop

19
2017-09-14 15:09



हम्म निष्पक्ष दूसरे उदाहरण होने के लिए सूची भी होनी चाहिए (या पहले टुपल?) - Mr_and_Mrs_D


यदि आप डेटा-स्ट्रक्चर को फ़्लैट करना चाहते हैं, जहां आप नहीं जानते कि यह कितना गहरा है, तो आप इसका उपयोग कर सकते हैं iteration_utilities.deepflatten1

>>> from iteration_utilities import deepflatten

>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> list(deepflatten(l, depth=1))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> l = [[1, 2, 3], [4, [5, 6]], 7, [8, 9]]
>>> list(deepflatten(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

यह जनरेटर है इसलिए आपको परिणाम को एक कास्ट करने की आवश्यकता है list या स्पष्ट रूप से इसे फिर से शुरू करें।


केवल एक स्तर को फ़्लैट करने के लिए और यदि प्रत्येक आइटम स्वयं ही अक्षम है तो आप इसका भी उपयोग कर सकते हैं iteration_utilities.flatten जो खुद ही एक पतली आवरण है itertools.chain.from_iterable:

>>> from iteration_utilities import flatten
>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> list(flatten(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

बस कुछ समय जोड़ने के लिए (निको श्लोमर उत्तर के आधार पर जिसमें इस उत्तर में प्रस्तुत समारोह शामिल नहीं था):

enter image description here

यह स्पैन किए गए मूल्यों की विशाल श्रृंखला के लिए समायोजित करने के लिए लॉग-लॉग प्लॉट है। गुणात्मक तर्क के लिए: निचला बेहतर है।

परिणाम दिखाते हैं कि अगर पुनरावर्तनीय में केवल कुछ आंतरिक पुनरावृत्त होते हैं sum सबसे तेज़ होगा, हालांकि लंबे समय तक केवल पुनरावृत्तियों के लिए itertools.chain.from_iterable, iteration_utilities.deepflatten या नेस्टेड समझ के साथ उचित प्रदर्शन है itertools.chain.from_iterable सबसे तेज़ (जैसा कि पहले से निको श्लोमर द्वारा देखा गया है)।

from itertools import chain
from functools import reduce
from collections import Iterable  # or from collections.abc import Iterable
import operator
from iteration_utilities import deepflatten

def nested_list_comprehension(lsts):
    return [item for sublist in lsts for item in sublist]

def itertools_chain_from_iterable(lsts):
    return list(chain.from_iterable(lsts))

def pythons_sum(lsts):
    return sum(lsts, [])

def reduce_add(lsts):
    return reduce(lambda x, y: x + y, lsts)

def pylangs_flatten(lsts):
    return list(flatten(lsts))

def flatten(items):
    """Yield items from any nested iterable; see REF."""
    for x in items:
        if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
            yield from flatten(x)
        else:
            yield x

def reduce_concat(lsts):
    return reduce(operator.concat, lsts)

def iteration_utilities_deepflatten(lsts):
    return list(deepflatten(lsts, depth=1))


from simple_benchmark import benchmark

b = benchmark(
    [nested_list_comprehension, itertools_chain_from_iterable, pythons_sum, reduce_add,
     pylangs_flatten, reduce_concat, iteration_utilities_deepflatten],
    arguments={2**i: [[0]*5]*(2**i) for i in range(1, 13)},
    argument_name='number of inner lists'
)

b.plot()

1 अस्वीकरण: मैं उस पुस्तकालय का लेखक हूं


17
2017-11-26 00:20



sum मनमाने ढंग से अनुक्रमों पर काम नहीं करता है क्योंकि यह शुरू होता है 0, बनाना functools.reduce(operator.add, sequences) प्रतिस्थापन (क्या हमें खुशी नहीं है कि वे हटा दिए गए हैं reduce बिल्टिन से?)। जब प्रकार ज्ञात होते हैं तो यह उपयोग करने के लिए तेज़ हो सकता है type.__add__। - Yann Vernier
@YannVernier जानकारी के लिए धन्यवाद। मैंने सोचा कि मैंने पाइथन 3.6 पर इन बेंचमार्क चलाए और यह काम किया sum। क्या आपको पता है कि किस पायथन संस्करणों ने काम करना बंद कर दिया है? - MSeifert
मैं कुछ गलत था। 0 केवल डिफ़ॉल्ट प्रारंभिक मान है, इसलिए यदि कोई इसका उपयोग करता है तो यह काम करता है तर्क शुरू करें एक खाली सूची के साथ शुरू करने के लिए ... लेकिन यह अभी भी विशेष मामलों के तार और मुझे शामिल होने का उपयोग करने के लिए कहता है। यह कार्यान्वित है foldl के बजाय foldl1। एक ही मुद्दा 2.7 में पॉप अप करता है। - Yann Vernier


कारण आपके फ़ंक्शन ने काम नहीं किया: विस्तार विस्तार से सरणी को बढ़ाता है और इसे वापस नहीं करता है। आप अभी भी कुछ चाल का उपयोग कर, लैम्ब्डा से एक्स वापस कर सकते हैं:

reduce(lambda x,y: x.extend(y) or x, l)

नोट: सूची सूचियों पर + से अधिक कुशल है।


13
2018-06-04 20:47



extend के रूप में बेहतर इस्तेमाल किया जाता है newlist = [], extend = newlist.extend, for sublist in l: extend(l) क्योंकि यह (बल्कि बड़े) ओवरहेड से बचाता है lambda, विशेषता लुकअप पर x, और यह or। - agf