it-swarm.com.de

Eine flache Liste in Python

Gibt es eine einfache Möglichkeit, eine Liste von Iterables mit einem Listenverständnis zu reduzieren, oder ist dies nicht der Fall, was würden Sie alle als die beste Möglichkeit betrachten, eine flache Liste wie diese zu reduzieren, um Leistung und Lesbarkeit in Einklang zu bringen?

Ich habe versucht, eine solche Liste mit einem verschachtelten Listenverständnis zu reduzieren:

[image for image in menuitem for menuitem in list_of_menuitems]

Aber ich bekomme Ärger mit der Sorte NameError, weil die name 'menuitem' is not defined. Nachdem ich über Stack Overflow gegoogelt und mich umgesehen hatte, erhielt ich die gewünschten Ergebnisse mit einer reduce -Anweisung:

reduce(list.__add__, map(lambda x: list(x), list_of_menuitems))

Aber diese Methode ist ziemlich unlesbar, weil ich diesen list(x) -Aufruf dort brauche, weil x ein Django QuerySet -Objekt ist.

Fazit :

Vielen Dank an alle, die zu dieser Frage beigetragen haben. Hier ist eine Zusammenfassung dessen, was ich gelernt habe. Ich mache dies auch zu einem Community-Wiki, falls andere diese Beobachtungen ergänzen oder korrigieren möchten.

Meine ursprüngliche Reduce-Anweisung ist überflüssig und sollte folgendermaßen geschrieben werden:

>>> reduce(list.__add__, (list(mi) for mi in list_of_menuitems))

Dies ist die korrekte Syntax für ein verschachteltes Listenverständnis (Brillante Zusammenfassung dF !):

>>> [image for mi in list_of_menuitems for image in mi]

Keine dieser Methoden ist jedoch so effizient wie die Verwendung von itertools.chain:

>>> from itertools import chain
>>> list(chain(*list_of_menuitems))

Und wie @cdleary bemerkt, ist es wahrscheinlich besser, * Operator-Magie zu vermeiden, indem Sie chain.from_iterable Wie folgt verwenden:

>>> chain = itertools.chain.from_iterable([[1,2],[3],[5,89],[],[6]])
>>> print(list(chain))
>>> [1, 2, 3, 5, 89, 6]
379
Prairiedogg

Wenn Sie nur über eine reduzierte Version der Datenstruktur iterieren möchten und keine indexierbare Sequenz benötigen, ziehen Sie itertools.chain und company in Betracht.

>>> list_of_menuitems = [['image00', 'image01'], ['image10'], []]
>>> import itertools
>>> chain = itertools.chain(*list_of_menuitems)
>>> print(list(chain))
['image00', 'image01', 'image10']

Es funktioniert für alles, was iterabel ist, einschließlich Djangos iterablem QuerySets, das Sie anscheinend in der Frage verwenden.

Bearbeiten: Dies ist wahrscheinlich sowieso so gut wie eine Verkleinerung, da bei der Verkleinerung derselbe Aufwand anfällt, wenn die Elemente in die Liste kopiert werden, die gerade erweitert wird. chain verursacht diesen (gleichen) Aufwand nur, wenn Sie am Ende list(chain) ausführen.

Meta-Edit: Tatsächlich ist dies weniger aufwändig als die vorgeschlagene Lösung der Frage, da Sie die temporären Listen, die Sie erstellen, wenn Sie das Original mit dem temporären Element erweitern, wegwerfen .

Edit: As sagt JF Sebastianitertools.chain.from_iterable Vermeidet das Auspacken und du solltest das benutzen, um * Magie, aber die Timeit-App zeigt vernachlässigbare Leistungsunterschiede.

288
cdleary

Du hast es fast geschafft! Die Möglichkeit, geschachtelte Listen zu verstehen besteht darin, die for -Anweisungen in der gleichen Reihenfolge anzuordnen, in der sie in regulären geschachtelten for -Anweisungen ablaufen würden.

Also das

for inner_list in outer_list:
    for item in inner_list:
        ...

entspricht

[... for inner_list in outer_list for item in inner_list]

Also du möchtest

[image for menuitem in list_of_menuitems for image in menuitem]
265
dF.

@ S.Lott : Du hast mich dazu inspiriert, eine Timeit-App zu schreiben.

Ich nahm an, dass dies auch von der Anzahl der Partitionen abhängt (Anzahl der Iteratoren in der Containerliste). In Ihrem Kommentar wurde nicht erwähnt, wie viele Partitionen von den dreißig Elementen vorhanden waren. Dieser Plot reduziert in jedem Durchgang tausend Elemente mit einer unterschiedlichen Anzahl von Partitionen. Die Elemente werden gleichmäßig auf die Partitionen verteilt.

Flattening Comparison

Code (Python 2.6):

#!/usr/bin/env python2.6

"""Usage: %prog item_count"""

from __future__ import print_function

import collections
import itertools
import operator
from timeit import Timer
import sys

import matplotlib.pyplot as pyplot

def itertools_flatten(iter_lst):
    return list(itertools.chain(*iter_lst))

def itertools_iterable_flatten(iter_iter):
    return list(itertools.chain.from_iterable(iter_iter))

def reduce_flatten(iter_lst):
    return reduce(operator.add, map(list, iter_lst))

def reduce_lambda_flatten(iter_lst):
    return reduce(operator.add, map(lambda x: list(x), [i for i in iter_lst]))

def comprehension_flatten(iter_lst):
    return list(item for iter_ in iter_lst for item in iter_)

METHODS = ['itertools', 'itertools_iterable', 'reduce', 'reduce_lambda',
           'comprehension']

def _time_test_assert(iter_lst):
    """Make sure all methods produce an equivalent value.
    :raise AssertionError: On any non-equivalent value."""
    callables = (globals()[method + '_flatten'] for method in METHODS)
    results = [callable(iter_lst) for callable in callables]
    if not all(result == results[0] for result in results[1:]):
        raise AssertionError

def time_test(partition_count, item_count_per_partition, test_count=10000):
    """Run flatten methods on a list of :param:`partition_count` iterables.
    Normalize results over :param:`test_count` runs.
    :return: Mapping from method to (normalized) microseconds per pass.
    """
    iter_lst = [[dict()] * item_count_per_partition] * partition_count
    print('Partition count:    ', partition_count)
    print('Items per partition:', item_count_per_partition)
    _time_test_assert(iter_lst)
    test_str = 'flatten(%r)' % iter_lst
    result_by_method = {}
    for method in METHODS:
        setup_str = 'from test import %s_flatten as flatten' % method
        t = Timer(test_str, setup_str)
        per_pass = test_count * t.timeit(number=test_count) / test_count
        print('%20s: %.2f usec/pass' % (method, per_pass))
        result_by_method[method] = per_pass
    return result_by_method

if __== '__main__':
    if len(sys.argv) != 2:
        raise ValueError('Need a number of items to flatten')
    item_count = int(sys.argv[1])
    partition_counts = []
    pass_times_by_method = collections.defaultdict(list)
    for partition_count in xrange(1, item_count):
        if item_count % partition_count != 0:
            continue
        items_per_partition = item_count / partition_count
        result_by_method = time_test(partition_count, items_per_partition)
        partition_counts.append(partition_count)
        for method, result in result_by_method.iteritems():
            pass_times_by_method[method].append(result)
    for method, pass_times in pass_times_by_method.iteritems():
        pyplot.plot(partition_counts, pass_times, label=method)
    pyplot.legend()
    pyplot.title('Flattening Comparison for %d Items' % item_count)
    pyplot.xlabel('Number of Partitions')
    pyplot.ylabel('Microseconds')
    pyplot.show()

Bearbeiten: Beschlossen, es zu einem Community-Wiki zu machen.

Hinweis: METHODS sollte wahrscheinlich mit einem Dekorateur akkumuliert werden, aber ich denke, es wäre für die Leute einfacher, so zu lesen.

125
cdleary

sum(list_of_lists, []) würde es verflachen.

l = [['image00', 'image01'], ['image10'], []]
print sum(l,[]) # prints ['image00', 'image01', 'image10']
45
Prem Anand

Diese Lösung funktioniert für beliebige Schachtelungstiefen - nicht nur für die "Listen" -Tiefe, auf die einige (alle?) Der anderen Lösungen beschränkt sind:

def flatten(x):
    result = []
    for el in x:
        if hasattr(el, "__iter__") and not isinstance(el, basestring):
            result.extend(flatten(el))
        else:
            result.append(el)
    return result

Es ist die Rekursion, die eine beliebige Verschachtelung der Tiefe ermöglicht - bis Sie die maximale Rekursionstiefe erreicht haben ...

37
James Brady

In Python 2.6 mit chain.from_iterable() :

>>> from itertools import chain
>>> list(chain.from_iterable(mi.image_set.all() for mi in h.get_image_menu()))

Das Erstellen einer Zwischenliste wird vermieden.

23
jfs

Leistungsergebnisse. Überarbeitet.

import itertools
def itertools_flatten( aList ):
    return list( itertools.chain(*aList) )

from operator import add
def reduce_flatten1( aList ):
    return reduce(add, map(lambda x: list(x), [mi for mi in aList]))

def reduce_flatten2( aList ):
    return reduce(list.__add__, map(list, aList))

def comprehension_flatten( aList ):
    return list(y for x in aList for y in x)

Ich habe eine zweistufige Liste mit 30 Elementen 1000-mal zusammengefasst

itertools_flatten     0.00554
comprehension_flatten 0.00815
reduce_flatten2       0.01103
reduce_flatten1       0.01404

Reduzieren ist immer eine schlechte Wahl.

22
S.Lott

Es scheint eine Verwechslung mit operator.add Zu geben! Wenn Sie zwei Listen zusammenfassen, lautet der korrekte Begriff für diese Liste concat, nicht addieren. operator.concat Ist das, was Sie verwenden müssen.

Wenn Sie funktional denken, ist es so einfach:

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

Wenn Sie einen Tupel angeben, erhalten Sie einen Tupel zurück. Versuchen wir es mit einer Liste:

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

Aha, du bekommst eine Liste zurück.

Wie wäre es mit Leistung ::

>>> 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

from_iterable ist ziemlich schnell! Aber es ist kein Vergleich mit concat zu reduzieren.

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

Aus meinem Kopf heraus können Sie das Lambda eliminieren:

reduce(list.__add__, map(list, [mi.image_set.all() for mi in list_of_menuitems]))

Oder eliminieren Sie sogar die Karte, da Sie bereits einen Listen-Comp haben:

reduce(list.__add__, [list(mi.image_set.all()) for mi in list_of_menuitems])

Sie können dies auch einfach als eine Summe von Listen ausdrücken:

sum([list(mi.image_set.all()) for mi in list_of_menuitems], [])
8
recursive

Hier ist die richtige Lösung unter Verwendung von Listenverständnissen (sie sind in der Frage rückständig):

>>> join = lambda it: (y for x in it for y in x)
>>> list(join([[1,2],[3,4,5],[]]))
[1, 2, 3, 4, 5]

In deinem Fall wäre es

[image for menuitem in list_of_menuitems for image in menuitem.image_set.all()]

oder Sie könnten join verwenden und sagen

join(menuitem.image_set.all() for menuitem in list_of_menuitems)

In beiden Fällen war das gotcha die Verschachtelung der for Schleifen.

7
Josh Lee

Hier ist eine Version für mehrere Listenebenen mit collectons.Iterable:

import collections

def flatten(o, flatten_condition=lambda i: isinstance(i,
               collections.Iterable) and not isinstance(i, str)):
    result = []
    for i in o:
        if flatten_condition(i):
            result.extend(flatten(i, flatten_condition))
        else:
            result.append(i)
    return result
4
Pierre Thibault

Diese Version ist ein Generator. Schwächen Sie es, wenn Sie eine Liste wünschen.

def list_or_Tuple(l):
    return isinstance(l,(list,Tuple))
## predicate will select the container  to be flattened
## write your own as required
## this one flattens every list/Tuple


def flatten(seq,predicate=list_or_Tuple):        
    ## recursive generator 
    for i in seq:
        if predicate(seq):
            for j in flatten(i):
                yield j
        else:
            yield i

Sie können ein Prädikat hinzufügen, um diejenigen zu reduzieren, die eine Bedingung erfüllen

Entnommen aus python cookbook

3
devsaw

Nach meiner Erfahrung ist der effizienteste Weg, eine Liste von Listen zu reduzieren:

flat_list = []
map(flat_list.extend, list_of_list)

Einige zeitliche Vergleiche mit den anderen vorgeschlagenen Methoden:

list_of_list = [range(10)]*1000
%timeit flat_list=[]; map(flat_list.extend, list_of_list)
#10000 loops, best of 3: 119 µs per loop
%timeit flat_list=list(itertools.chain.from_iterable(list_of_list))
#1000 loops, best of 3: 210 µs per loop
%timeit flat_list=[i for sublist in list_of_list for i in sublist]
#1000 loops, best of 3: 525 µs per loop
%timeit flat_list=reduce(list.__add__,list_of_list)
#100 loops, best of 3: 18.1 ms per loop

Jetzt erscheint der Effizienzgewinn bei der Verarbeitung längerer Unterlisten besser:

list_of_list = [range(1000)]*10
%timeit flat_list=[]; map(flat_list.extend, list_of_list)
#10000 loops, best of 3: 60.7 µs per loop
%timeit flat_list=list(itertools.chain.from_iterable(list_of_list))
#10000 loops, best of 3: 176 µs per loop

Und diese Methode funktioniert auch mit jedem iterativen Objekt:

class SquaredRange(object):
    def __init__(self, n): 
        self.range = range(n)
    def __iter__(self):
        for i in self.range: 
            yield i**2

list_of_list = [SquaredRange(5)]*3
flat_list = []
map(flat_list.extend, list_of_list)
print flat_list
#[0, 1, 4, 9, 16, 0, 1, 4, 9, 16, 0, 1, 4, 9, 16]
3
Juh_

Wenn Sie eine kompliziertere Liste mit nicht iterierbaren Elementen oder mit einer Tiefe von mehr als 2 erstellen müssen, können Sie folgende Funktion verwenden:

def flat_list(list_to_flat):
    if not isinstance(list_to_flat, list):
        yield list_to_flat
    else:
        for item in list_to_flat:
            yield from flat_list(item)

Es wird ein Generatorobjekt zurückgegeben, das Sie mit der Funktion list() in eine Liste konvertieren können. Beachten Sie, dass die Syntax yield from Ab python3.3 verfügbar ist, Sie können jedoch stattdessen die explizite Iteration verwenden.
Beispiel:

>>> a = [1, [2, 3], [1, [2, 3, [1, [2, 3]]]]]
>>> print(list(flat_list(a)))
[1, 2, 3, 1, 2, 3, 1, 2, 3]
3
DartLenin

hast du versucht zu plätten? From matplotlib.cbook.flatten (seq, scalarp =) ?

l=[[1,2,3],[4,5,6], [7], [8,9]]*33

run("list(flatten(l))")
         3732 function calls (3303 primitive calls) in 0.007 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.007    0.007 <string>:1(<module>)
      429    0.001    0.000    0.001    0.000 cbook.py:475(iterable)
      429    0.002    0.000    0.003    0.000 cbook.py:484(is_string_like)
      429    0.002    0.000    0.006    0.000 cbook.py:565(is_scalar_or_string)
  727/298    0.001    0.000    0.007    0.000 cbook.py:605(flatten)
      429    0.000    0.000    0.001    0.000 core.py:5641(isMaskedArray)
      858    0.001    0.000    0.001    0.000 {isinstance}
      429    0.000    0.000    0.000    0.000 {iter}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}



l=[[1,2,3],[4,5,6], [7], [8,9]]*66

run("list(flatten(l))")
         7461 function calls (6603 primitive calls) in 0.007 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.007    0.007 <string>:1(<module>)
      858    0.001    0.000    0.001    0.000 cbook.py:475(iterable)
      858    0.002    0.000    0.003    0.000 cbook.py:484(is_string_like)
      858    0.002    0.000    0.006    0.000 cbook.py:565(is_scalar_or_string)
 1453/595    0.001    0.000    0.007    0.000 cbook.py:605(flatten)
      858    0.000    0.000    0.001    0.000 core.py:5641(isMaskedArray)
     1716    0.001    0.000    0.001    0.000 {isinstance}
      858    0.000    0.000    0.000    0.000 {iter}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}



l=[[1,2,3],[4,5,6], [7], [8,9]]*99

run("list(flatten(l))")
         11190 function calls (9903 primitive calls) in 0.010 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.010    0.010 <string>:1(<module>)
     1287    0.002    0.000    0.002    0.000 cbook.py:475(iterable)
     1287    0.003    0.000    0.004    0.000 cbook.py:484(is_string_like)
     1287    0.002    0.000    0.009    0.000 cbook.py:565(is_scalar_or_string)
 2179/892    0.001    0.000    0.010    0.000 cbook.py:605(flatten)
     1287    0.001    0.000    0.001    0.000 core.py:5641(isMaskedArray)
     2574    0.001    0.000    0.001    0.000 {isinstance}
     1287    0.000    0.000    0.000    0.000 {iter}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}



l=[[1,2,3],[4,5,6], [7], [8,9]]*132

run("list(flatten(l))")
         14919 function calls (13203 primitive calls) in 0.013 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.013    0.013 <string>:1(<module>)
     1716    0.002    0.000    0.002    0.000 cbook.py:475(iterable)
     1716    0.004    0.000    0.006    0.000 cbook.py:484(is_string_like)
     1716    0.003    0.000    0.011    0.000 cbook.py:565(is_scalar_or_string)
2905/1189    0.002    0.000    0.013    0.000 cbook.py:605(flatten)
     1716    0.001    0.000    0.001    0.000 core.py:5641(isMaskedArray)
     3432    0.001    0.000    0.001    0.000 {isinstance}
     1716    0.001    0.000    0.001    0.000 {iter}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler'

[~ # ~] update [~ # ~] Was mir eine andere Idee gab:

l=[[1,2,3],[4,5,6], [7], [8,9]]*33

run("flattenlist(l)")
         564 function calls (432 primitive calls) in 0.000 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    133/1    0.000    0.000    0.000    0.000 <ipython-input-55-39b139bad497>:4(flattenlist)
        1    0.000    0.000    0.000    0.000 <string>:1(<module>)
      429    0.000    0.000    0.000    0.000 {isinstance}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}



l=[[1,2,3],[4,5,6], [7], [8,9]]*66

run("flattenlist(l)")
         1125 function calls (861 primitive calls) in 0.001 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    265/1    0.001    0.000    0.001    0.001 <ipython-input-55-39b139bad497>:4(flattenlist)
        1    0.000    0.000    0.001    0.001 <string>:1(<module>)
      858    0.000    0.000    0.000    0.000 {isinstance}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}



l=[[1,2,3],[4,5,6], [7], [8,9]]*99

run("flattenlist(l)")
         1686 function calls (1290 primitive calls) in 0.001 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    397/1    0.001    0.000    0.001    0.001 <ipython-input-55-39b139bad497>:4(flattenlist)
        1    0.000    0.000    0.001    0.001 <string>:1(<module>)
     1287    0.000    0.000    0.000    0.000 {isinstance}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}



l=[[1,2,3],[4,5,6], [7], [8,9]]*132

run("flattenlist(l)")
         2247 function calls (1719 primitive calls) in 0.002 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    529/1    0.001    0.000    0.002    0.002 <ipython-input-55-39b139bad497>:4(flattenlist)
        1    0.000    0.000    0.002    0.002 <string>:1(<module>)
     1716    0.001    0.000    0.001    0.000 {isinstance}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}



l=[[1,2,3],[4,5,6], [7], [8,9]]*1320

run("flattenlist(l)")
         22443 function calls (17163 primitive calls) in 0.016 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
   5281/1    0.011    0.000    0.016    0.016 <ipython-input-55-39b139bad497>:4(flattenlist)
        1    0.000    0.000    0.016    0.016 <string>:1(<module>)
    17160    0.005    0.000    0.005    0.000 {isinstance}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

Um zu testen, wie effektiv es ist, wenn rekursiv tiefer wird: Um wie viel tiefer?

l=[[1,2,3],[4,5,6], [7], [8,9]]*1320

new=[l]*33

run("flattenlist(new)")
         740589 function calls (566316 primitive calls) in 0.418 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
 174274/1    0.281    0.000    0.417    0.417 <ipython-input-55-39b139bad497>:4(flattenlist)
        1    0.001    0.001    0.418    0.418 <string>:1(<module>)
   566313    0.136    0.000    0.136    0.000 {isinstance}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}



new=[l]*66

run("flattenlist(new)")
         1481175 function calls (1132629 primitive calls) in 0.809 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
 348547/1    0.542    0.000    0.807    0.807 <ipython-input-55-39b139bad497>:4(flattenlist)
        1    0.002    0.002    0.809    0.809 <string>:1(<module>)
  1132626    0.266    0.000    0.266    0.000 {isinstance}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}



new=[l]*99

run("flattenlist(new)")
         2221761 function calls (1698942 primitive calls) in 1.211 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
 522820/1    0.815    0.000    1.208    1.208 <ipython-input-55-39b139bad497>:4(flattenlist)
        1    0.002    0.002    1.211    1.211 <string>:1(<module>)
  1698939    0.393    0.000    0.393    0.000 {isinstance}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}



new=[l]*132

run("flattenlist(new)")
         2962347 function calls (2265255 primitive calls) in 1.630 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
 697093/1    1.091    0.000    1.627    1.627 <ipython-input-55-39b139bad497>:4(flattenlist)
        1    0.003    0.003    1.630    1.630 <string>:1(<module>)
  2265252    0.536    0.000    0.536    0.000 {isinstance}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}



new=[l]*1320

run("flattenlist(new)")
         29623443 function calls (22652523 primitive calls) in 16.103 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
6970921/1   10.842    0.000   16.069   16.069 <ipython-input-55-39b139bad497>:4(flattenlist)
        1    0.034    0.034   16.103   16.103 <string>:1(<module>)
 22652520    5.227    0.000    5.227    0.000 {isinstance}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

Ich wette, "Flattenlist" Ich werde dies für eine lange Zeit anstelle von Matploblib verwenden, es sei denn, ich möchte einen Ertragsgenerator und ein schnelles Ergebnis, wie es "Flatten" in matploblib.cbook verwendet

Das ist schnell.

  • Und hier ist der Code

:

typ=(list,Tuple)


def flattenlist(d):
    thelist = []
    for x in d:
        if not isinstance(x,typ):
            thelist += [x]
        else:
            thelist += flattenlist(x)
    return thelist
3
user2290820
def is_iterable(item):
   return isinstance(item, list) or isinstance(item, Tuple)


def flatten(items):
    for i in items:
        if is_iterable(item):
            for m in flatten(i):
                yield m
        else:
            yield i

Prüfung:

print list(flatten2([1.0, 2, 'a', (4,), ((6,), (8,)), (((8,),(9,)), ((12,),(10)))]))
3
kopos

pylab bietet eine Abflachung: Link zu Numpy Flatten

2
ntg

Wenn Sie nach einem integrierten, einfachen Einzeiler suchen, können Sie Folgendes verwenden:

a = [[1, 2, 3], [4, 5, 6]
b = [i[x] for i in a for x in range(len(i))]
print b

kehrt zurück

[1, 2, 3, 4, 5, 6]
2
Bottersnike

Wie wäre es mit:

from operator import add
reduce(add, map(lambda x: list(x.image_set.all()), [mi for mi in list_of_menuitems]))

Guido rät jedoch davon ab, zu viel Code in einer einzigen Zeile auszuführen, da dies die Lesbarkeit beeinträchtigt. Wenn überhaupt, gibt es nur einen minimalen Leistungsgewinn, wenn Sie das tun, was Sie in einer einzelnen Zeile im Vergleich zu mehreren Zeilen wollen.

2
daniel

Wenn jedes Element in der Liste eine Zeichenfolge ist (und Zeichenfolgen in diesen Zeichenfolgen "" anstelle von "'verwenden), können Sie reguläre Ausdrücke verwenden (Modul re).

>>> flattener = re.compile("\'.*?\'")
>>> flattener
<_sre.SRE_Pattern object at 0x10d439ca8>
>>> stred = str(in_list)
>>> outed = flattener.findall(stred)

Der obige Code konvertiert in_list in einen String, verwendet den regulären Ausdruck, um alle Teilzeichenfolgen in Anführungszeichen (d. H. Jedes Element der Liste) zu finden und spuckt sie als Liste aus.

1
user22723

Eine einfache Alternative ist numpy's concatenate , aber es konvertiert den Inhalt in float:

import numpy as np
print np.concatenate([[1,2],[3],[5,89],[],[6]])
# array([  1.,   2.,   3.,   5.,  89.,   6.])
print list(np.concatenate([[1,2],[3],[5,89],[],[6]]))
# [  1.,   2.,   3.,   5.,  89.,   6.]
1
strpeter

Der einfachste Weg, dies in Python 2 oder 3) zu erreichen, ist die Verwendung der morph -Bibliothek mit pip install morph.

Der Code lautet:

import morph

list = [[1,2],[3],[5,89],[],[6]]
flattened_list = morph.flatten(list)  # returns [1, 2, 3, 5, 89, 6]
1
YPCrumble

In Python 3.4 können Sie Folgendes tun:

[*innerlist for innerlist in outer_list]
0
elyase