Hoe maak je een platte lijst van een lijst met lijsten

Is er een snelkoppeling om een ​​eenvoudige lijst te maken van een lijst met lijsten in Python?

Ik kan het in een for-lus doen, maar is er een coole “one-liner”?

Ik heb het geprobeerd met functools.reduce():

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

Maar ik krijg deze foutmelding:

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

Antwoord 1, autoriteit 100%

Gegeven een lijst met lijsten t,

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

wat betekent:

flat_list = []
for sublist in t:
    for item in sublist:
        flat_list.append(item)

is sneller dan de snelkoppelingen die tot nu toe zijn gepost. (tis de lijst die moet worden afgevlakt.)

Hier is de bijbehorende functie:

def flatten(t):
    return [item for sublist in t for item in sublist]

Als bewijs kunt u de module timeitin de standaardbibliotheek gebruiken:

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

Uitleg: de sneltoetsen op basis van +(inclusief het impliciete gebruik in sum) zijn, noodzakelijkerwijs, O(T**2)als er T-sublijsten zijn — naarmate de lijst met tussenresultaten langer wordt, wordt bij elke stap een nieuw object van de tussenresultatenlijst toegewezen en moeten alle items in het vorige tussenresultaat worden gekopieerd (evenals een paar nieuwe toegevoegd aan het einde). Dus, voor de eenvoud en zonder daadwerkelijk verlies van algemeenheid, stel dat je T-sublijsten hebt van elk k items: de eerste k items worden T-1 keer heen en weer gekopieerd, de tweede k items T-2 keer, enzovoort; totaal aantal kopieën is k maal de som van x voor x van 1 tot T uitgesloten, d.w.z. k * (T**2)/2.

Het lijstbegrip genereert slechts één lijst, één keer, en kopieert elk item (van de oorspronkelijke woonplaats naar de resultatenlijst) ook precies één keer.


Antwoord 2, autoriteit 32%

U kunt itertools.chain():

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

Of je kunt itertools.chain.from_iterable()waarvoor u de lijst niet hoeft uit te pakken met de *operator:

merged = list(itertools.chain.from_iterable(list2d))

Antwoord 3, autoriteit 18%

Opmerking van de auteur: dit is inefficiënt. Maar leuk, want monoïdenzijn geweldig. Het is niet geschikt voor productie Python-code.

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

Dit telt alleen de elementen van iterabel op die in het eerste argument zijn doorgegeven, waarbij het tweede argument wordt behandeld als de beginwaarde van de som (indien niet gegeven, wordt in plaats daarvan 0gebruikt en in dit geval krijgt u een foutmelding ).

Omdat je geneste lijsten optelt, krijg je in feite [1,3]+[2,4]als resultaat van sum([[1,3],[2,4]],[]), wat gelijk is aan [1,3,2,4].

Houd er rekening mee dat dit alleen werkt op lijsten met lijsten. Voor lijsten van lijsten met lijsten heeft u een andere oplossing nodig.


Antwoord 4, autoriteit 11%

Ik heb de meeste voorgestelde oplossingen getest met perfplot(een huisdierproject van mij, in wezen een wrapper rond timeit), en gevonden

import functools
import operator
functools.reduce(operator.iconcat, a, [])

om de snelste oplossing te zijn, zowel wanneer veel kleine lijsten als weinig lange lijsten aaneengeschakeld zijn. (operator.iaddis even snel.)

voer hier de afbeeldingsbeschrijving in

voer hier de afbeeldingsbeschrijving in


Code om de plot te reproduceren:

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 functools_reduce_iconcat(a):
    return functools.reduce(operator.iconcat, 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,
    # setup=lambda n: [list(range(n))] * 10,
    kernels=[
        forfor,
        sum_brackets,
        functools_reduce,
        functools_reduce_iconcat,
        itertools_chain,
        numpy_flat,
        numpy_concatenate,
    ],
    n_range=[2 ** k for k in range(16)],
    xlabel="num lists (of length 10)",
    # xlabel="len lists (10 lists total)"
)

Antwoord 5, autoriteit 5%

Vind het wiel niet opnieuw uit

Als u –

. gebruikt

Django:

>>> from django.contrib.admin.utils import flatten
>>> l = [[1,2,3], [4,5], [6]]
>>> flatten(l)
>>> [1, 2, 3, 4, 5, 6]

Panda’s:

>>> from pandas.core.common import flatten
>>> list(flatten(l))

Itertools:

>>> import itertools
>>> flatten = itertools.chain.from_iterable
>>> list(flatten(l))

Matplotlib

>>> from matplotlib.cbook import flatten
>>> list(flatten(l))

Unipath:

>>> from unipath.path import flatten
>>> list(flatten(l))

Setuptools:

>>> from setuptools.namespaces import flatten
>>> list(flatten(l))

Antwoord 6, autoriteit 4%

>>> from functools import reduce
>>> 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]

De methode extend()in uw voorbeeld wijzigt xin plaats van een bruikbare waarde te retourneren (die functools.reduce()verwacht).

Een snellere manier om de reduce-versie te doen zou zijn

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

Antwoord 7, autoriteit 2%

Hier is een algemene benadering die van toepassing is op getallen, tekenreeksen, genestelijsten en gemengdecontainers. Dit kan zowel eenvoudige als gecompliceerde containers plat maken (zie ook Demo).

Code

from typing import Iterable 
#from collections import Iterable                            # < py38
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

Opmerkingen:

  • In Python 3 kan yield from flatten(x)for sub_x in flatten(x): yield sub_x
  • In Python 3.8, abstracte basisklassenzijn verplaatstvan collection.abcnaar de module typing.

Demo

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

Referentie

  • Deze oplossing is aangepast van een recept in Beazley, D. en B. Jones. Recept 4.14, Python Cookbook 3rd Ed., O’Reilly Media Inc. Sebastopol, CA: 2013.
  • Een eerdere SO-postgevonden, mogelijk de originele demonstratie.

Antwoord 8

Als je een gegevensstructuur wilt afvlakken waarvan je niet weet hoe diep deze is genest, kun je 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]

Het is een generator, dus je moet het resultaat casten naar een listof er expliciet overheen gaan.


Als u slechts één niveau wilt afvlakken en als elk van de items zelf itereerbaar is, kunt u ook iteration_utilities.flattenwat zelf slechts een dunne wikkel rond 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]

Om wat timing toe te voegen (gebaseerd op Nico Schlomer’s antwoorddat de functie in dit antwoord niet bevatte):

voer hier de afbeeldingsbeschrijving in

Het is een log-log-plot om tegemoet te komen aan het enorme bereik van waarden die worden overspannen. Voor kwalitatieve redenering: lager is beter.

De resultaten laten zien dat als de iterable slechts een paar interne iterables bevat, sumhet snelst zal zijn, maar voor lange iterables alleen de itertools.chain.from_iterable, iteration_utilities.deepflattenof het geneste begrip hebben redelijke prestaties waarbij itertools.chain.from_iterablede snelste is (zoals al opgemerkt door Nico Schlomer).

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 Disclaimer: ik ben de auteur van die bibliotheek


Antwoord 9

Ik neem mijn verklaring terug. som is niet de winnaar. Hoewel het sneller is als de lijst klein is. Maar de prestaties verslechteren aanzienlijk bij grotere lijsten.

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

De sum-versie is nog meer dan een minuut actief en is nog niet verwerkt!

Voor middelgrote lijsten:

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

Gebruik kleine lijsten en timeit: number=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

Antwoord 10

Er lijkt verwarring te zijn met operator.add! Als je twee lijsten bij elkaar optelt, is de juiste term daarvoor concat, niet optellen. operator.concatis wat je moet gebruiken.

Als je functioneel denkt, is het zo eenvoudig als dit:

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

Je ziet dat reducehet reekstype respecteert, dus als je een tuple levert, krijg je een tuple terug. Laten we proberen met een lijst:

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

Aha, je krijgt een lijst terug.

Hoe zit het met de prestaties:

>>> 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_iterableis behoorlijk snel! Maar het is niet te vergelijken met 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

Antwoord 11

U hoeft niet verlengen. Dit zou goed moeten werken:

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

Antwoord 12

Overweeg om het pakket more_itertoolste installeren.

> pip install more_itertools

Het wordt geleverd met een implementatie voor flatten(bron, uit de itertools-recepten):

import more_itertools
lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(more_itertools.flatten(lst))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

Opmerking: zoals vermeld in de docs, flattenvereist een lijst met lijsten. Zie hieronder over het afvlakken van meer onregelmatige invoer.


Vanaf versie 2.4 kun je meer gecompliceerde, geneste iterables afvlakken met more_itertools.collapse(bron, bijgedragen door abarnet).

lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(more_itertools.collapse(lst)) 
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
lst = [[1, 2, 3], [[4, 5, 6]], [[[7]]], 8, 9]              # complex nesting
list(more_itertools.collapse(lst))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

Antwoord 13

De reden dat uw functie niet werkte, is omdat de extendeen array ter plaatse uitbreidt en niet retourneert. Je kunt nog steeds x retourneren van lambda, met zoiets als dit:

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

Opmerking: verlengen is efficiënter dan + op lijsten.


Antwoord 14

def flatten(l, a):
    for i in l:
        if isinstance(i, list):
            flatten(i, a)
        else:
            a.append(i)
    return a
print(flatten([[[1, [1,1, [3, [4,5,]]]], 2, 3], [4, 5],6], []))
# [1, 1, 1, 3, 4, 5, 2, 3, 4, 5, 6]

Antwoord 15

Recursieve versie

x = [1,2,[3,4],[5,[6,[7]]],8,9,[10]]
def flatten_list(k):
    result = list()
    for i in k:
        if isinstance(i,list):
            #The isinstance() function checks if the object (first argument) is an 
            #instance or subclass of classinfo class (second argument)
            result.extend(flatten_list(i)) #Recursive call
        else:
            result.append(i)
    return result
flatten_list(x)
#result = [1,2,3,4,5,6,7,8,9,10]

Antwoord 16

Het geaccepteerde antwoord werkte niet voor mij bij het omgaan met op tekst gebaseerde lijsten met variabele lengtes. Hier is een alternatieve benadering die voor mij werkte.

l = ['aaa', 'bb', 'cccccc', ['xx', 'yyyyyyy']]

Geaccepteerd antwoord dat nietwerkte:

flat_list = [item for sublist in l for item in sublist]
print(flat_list)
['a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'c', 'c', 'c', 'xx', 'yyyyyyy']

Nieuwe voorgestelde oplossing die voor mij werkte:

flat_list = []
_ = [flat_list.extend(item) if isinstance(item, list) else flat_list.append(item) for item in l if item]
print(flat_list)
['aaa', 'bb', 'cccccc', 'xx', 'yyyyyyy']

Antwoord 17

Een slechte eigenschap van Anil’s functiehierboven is dat het vereist dat de gebruiker altijd handmatig het tweede argument specificeert om een ​​lege lijst te zijn []. Dit zou in plaats daarvan een standaard moeten zijn. Vanwege de manier waarop Python-objecten werken, moeten deze in de functie worden geplaatst, niet in de argumenten.

Hier is een werkende functie:

def list_flatten(l, a=None):
    #check a
    if a is None:
        #initialize with empty list
        a = []
    for i in l:
        if isinstance(i, list):
            list_flatten(i, a)
        else:
            a.append(i)
    return a

Testen:

In [2]: lst = [1, 2, [3], [[4]],[5,[6]]]
In [3]: lst
Out[3]: [1, 2, [3], [[4]], [5, [6]]]
In [11]: list_flatten(lst)
Out[11]: [1, 2, 3, 4, 5, 6]

Antwoord 18

matplotlib.cbook.flatten()werkt voor geneste lijsten, zelfs als ze dieper nesten dan het voorbeeld.

import matplotlib
l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
print(list(matplotlib.cbook.flatten(l)))
l2 = [[1, 2, 3], [4, 5, 6], [7], [8, [9, 10, [11, 12, [13]]]]]
print list(matplotlib.cbook.flatten(l2))

Resultaat:

[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

Dit is 18x sneller dan underscore._.flatten:

Average time over 1000 trials of matplotlib.cbook.flatten: 2.55e-05 sec
Average time over 1000 trials of underscore._.flatten: 4.63e-04 sec
(time for underscore._)/(time for matplotlib.cbook) = 18.1233394636

Antwoord 19

Het volgende lijkt mij het eenvoudigst:

>>> import numpy as np
>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> print (np.concatenate(l))
[1 2 3 4 5 6 7 8 9]

Antwoord 20

Je kunt ook NumPy’s plat:

import numpy as np
list(np.array(l).flat)

Het werkt alleen als sublijsten identieke afmetingen hebben.


Antwoord 21

Persoonlijk vind ik het moeilijk om alle modules te onthouden die geïmporteerd moesten worden. Daarom heb ik de neiging om een ​​eenvoudige methode te gebruiken, ook al weet ik niet hoe de prestaties ervan worden vergeleken met andere antwoorden.

Als je alleen geneste lijsten wilt afvlakken, dan is het volgende voldoende:

def flatten(lst):
    for item in lst:
        if isinstance(item, list):
            yield from flatten(item)
        else:
            yield item
# test case:
a =[0, [], "fun", [1, 2, 3], [4, [5], 6], 3, [7], [8, 9]]
list(flatten(a))
# output 
# [0, 'fun', 1, 2, 3, 4, 5, 6, 3, 7, 8, 9]

Als u echter een lijst met iterables (lijst en/of tupels) wilt afvlakken, kan dit ook met een kleine wijziging:

from collections.abc import Iterable
def flatten(lst):
    for item in lst:
        if isinstance(item,Iterable) and not isinstance(item,str):
            yield from flatten(item)
        else:
            yield item
# test case:
a =[0, [], "fun", (1, 2, 3), [4, [5], (6)], 3, [7], [8, 9]]
list(flatten(a))
# output: 
# [0, 'fun', 1, 2, 3, 4, 5, 6, 3, 7, 8, 9]

Antwoord 22

u kunt de listextendmethode gebruiken, dit blijkt de snelste te zijn:

flat_list = []
for sublist in l:
    flat_list.extend(sublist)

prestaties:

import functools
import itertools
import numpy
import operator
import perfplot
def functools_reduce_iconcat(a):
    return functools.reduce(operator.iconcat, a, [])
def itertools_chain(a):
    return list(itertools.chain.from_iterable(a))
def numpy_flat(a):
    return list(numpy.array(a).flat)
def extend(a):
    n = []
    list(map(n.extend, a))
    return n 
perfplot.show(
    setup=lambda n: [list(range(10))] * n,
    kernels=[
        functools_reduce_iconcat, extend,itertools_chain, numpy_flat
        ],
    n_range=[2**k for k in range(16)],
    xlabel='num lists',
    )

uitvoer:
voer hier de afbeeldingsbeschrijving in


Antwoord 23

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

Het voordeel van deze oplossing ten opzichte van de meeste andere hier is dat als je een lijst hebt zoals:

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

Terwijl de meeste andere oplossingen een foutmelding geven, verwerkt deze oplossing ze.


Antwoord 24

Dit is een spel op de code van de originele poster. (Hij was niet ver weg)

f = []
list(map(f.extend, l))

Antwoord 25

Opmerking: het onderstaande is van toepassing op Python 3.3+ omdat het gebruikmaakt van yield_from. sixis ook een pakket van derden, hoewel het stabiel is. Als alternatief kunt u sys.versiongebruiken.


In het geval van obj = [[1, 2,], [3, 4], [5, 6]]zijn alle oplossingen hier goed, inclusief lijstbegrip en itertools.chain.from_iterable.

Beschouw echter dit iets complexere geval:

>>> obj = [[1, 2, 3], [4, 5], 6, 'abc', [7], [8, [9, 10]]]

Er zijn hier verschillende problemen:

  • Eén element, 6, is slechts een scalair; het is niet itereerbaar, dus de bovenstaande routes zullen hier mislukken.
  • Eén element, 'abc', istechnisch itereerbaar (alle strs zijn). Maar als je een beetje tussen de regels door leest, wil je het niet als zodanig behandelen – je wilt het als een enkel element behandelen.
  • Het laatste element, [8, [9, 10]]is zelf een geneste iterable. Basislijstbegrip en chain.from_iterableextraheren alleen “1 niveau lager.”

U kunt dit als volgt verhelpen:

>>> from collections import Iterable
>>> from six import string_types
>>> def flatten(obj):
...     for i in obj:
...         if isinstance(i, Iterable) and not isinstance(i, string_types):
...             yield from flatten(i)
...         else:
...             yield i
>>> list(flatten(obj))
[1, 2, 3, 4, 5, 6, 'abc', 7, 8, 9, 10]

Hier controleer je of het subelement (1) itereerbaar is met Iterable, een ABC van itertools, maar wil er ook zeker van zijn dat (2) het element niet“string is -vind ik leuk.”


Antwoord 26

Je kunt numpy gebruiken:
flat_list = list(np.concatenate(list_of_list))


Antwoord 27

Eenvoudige code voor underscore.pypakketfan

from underscore import _
_.flatten([[1, 2, 3], [4, 5, 6], [7], [8, 9]])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

Het lost alle flatten-problemen op (geen lijstitem of complexe nesting)

from underscore import _
# 1 is none list item
# [2, [3]] is complex nesting
_.flatten([1, [2, [3]], [4, 5, 6], [7], [8, 9]])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

Je kunt underscore.pyinstalleren met pip

pip install underscore.py

Antwoord 28

def flatten(alist):
    if alist == []:
        return []
    elif type(alist) is not list:
        return [alist]
    else:
        return flatten(alist[0]) + flatten(alist[1:])

Antwoord 29

flat_list = []
for i in list_of_list:
    flat_list+=i

Deze code werkt ook prima omdat het de lijst gewoon helemaal uitbreidt. Hoewel het veel op elkaar lijkt, maar er maar één voor lus heeft. Het is dus minder ingewikkeld dan het toevoegen van 2 for-lussen.


Antwoord 30

Als je bereid bent een klein beetje snelheid op te geven voor een schoner uiterlijk, dan zou je numpy.concatenate().tolist()of numpy.concatenate().ravel().tolist():

import numpy
l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]] * 99
%timeit numpy.concatenate(l).ravel().tolist()
1000 loops, best of 3: 313 µs per loop
%timeit numpy.concatenate(l).tolist()
1000 loops, best of 3: 312 µs per loop
%timeit [item for sublist in l for item in sublist]
1000 loops, best of 3: 31.5 µs per loop

Je kunt hier meer informatie vinden in de documentatie, numpy .concatenateen numpy.ravel.

Other episodes