Oui, je sais que ce sujet a déjà été traité ( ici , ici , ici , ici ), mais pour autant que je sache, toutes les solutions, sauf une, échouer sur une liste comme celle-ci:
L = [[[1, 2, 3], [4, 5]], 6]
Où la sortie souhaitée est
[1, 2, 3, 4, 5, 6]
Ou peut-être même mieux, un itérateur. La seule solution que j'ai vue qui fonctionne pour une imbrication arbitraire est trouvée dans cette question :
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
flatten(L)
Est-ce le meilleur modèle? Ai-je oublié quelque chose? Des problèmes?
L'utilisation des fonctions du générateur peut rendre votre exemple un peu plus facile à lire et probablement améliorer les performances.
def flatten(l):
for el in l:
if isinstance(el, collections.Iterable) and not isinstance(el, basestring):
for sub in flatten(el):
yield sub
else:
yield el
J'ai utilisé le Iterable ABC ajouté dans 2.6.
Dans Python 3, la variable basestring
n'est plus, mais vous pouvez utiliser un nuplet de str
et bytes
pour obtenir le même effet.
L'opérateur yield from
renvoie un élément d'un générateur à la fois. Cette syntaxe pour déléguer à un sous-générateur a été ajoutée dans 3.3
def flatten(l):
for el in l:
if isinstance(el, collections.Iterable) and not isinstance(el, (str, bytes)):
yield from flatten(el)
else:
yield el
Ma solution:
def flatten(x):
if isinstance(x, collections.Iterable):
return [a for i in x for a in flatten(i)]
else:
return [x]
Un peu plus concis, mais à peu près pareil.
Version génératrice de la solution non-récursive de @ unutbu, comme l'a demandé @Andrew dans un commentaire:
def genflat(l, ltypes=collections.Sequence):
l = list(l)
i = 0
while i < len(l):
while isinstance(l[i], ltypes):
if not l[i]:
l.pop(i)
i -= 1
break
else:
l[i:i + 1] = l[i]
yield l[i]
i += 1
Version légèrement simplifiée de ce générateur:
def genflat(l, ltypes=collections.Sequence):
l = list(l)
while l:
while l and isinstance(l[0], ltypes):
l[0:1] = l[0]
if l: yield l.pop(0)
Générateur utilisant la récursion et la frappe de canard (mis à jour pour Python 3):
def flatten(L):
for item in L:
try:
yield from flatten(item)
except TypeError:
yield item
list(flatten([[[1, 2, 3], [4, 5]], 6]))
>>>[1, 2, 3, 4, 5, 6]
Cette version de flatten
évite la limite de récursivité de python (et fonctionne donc avec des itérables imbriquées de manière arbitraire, profonde) C'est un générateur capable de gérer des chaînes et des itérables arbitraires (même infinis).
import itertools as IT
import collections
def flatten(iterable, ltypes=collections.Iterable):
remainder = iter(iterable)
while True:
first = next(remainder)
if isinstance(first, ltypes) and not isinstance(first, basestring):
remainder = IT.chain(first, remainder)
else:
yield first
Voici quelques exemples démontrant son utilisation:
print(list(IT.islice(flatten(IT.repeat(1)),10)))
# [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
print(list(IT.islice(flatten(IT.chain(IT.repeat(2,3),
{10,20,30},
'foo bar'.split(),
IT.repeat(1),)),10)))
# [2, 2, 2, 10, 20, 30, 'foo', 'bar', 1, 1]
print(list(flatten([[1,2,[3,4]]])))
# [1, 2, 3, 4]
seq = ([[chr(i),chr(i-32)] for i in xrange(ord('a'), ord('z')+1)] + range(0,9))
print(list(flatten(seq)))
# ['a', 'A', 'b', 'B', 'c', 'C', 'd', 'D', 'e', 'E', 'f', 'F', 'g', 'G', 'h', 'H',
# 'i', 'I', 'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N', 'o', 'O', 'p', 'P',
# 'q', 'Q', 'r', 'R', 's', 'S', 't', 'T', 'u', 'U', 'v', 'V', 'w', 'W', 'x', 'X',
# 'y', 'Y', 'z', 'Z', 0, 1, 2, 3, 4, 5, 6, 7, 8]
Bien que flatten
puisse gérer des générateurs infinis, il ne peut pas gérer une imbrication infinie:
def infinitely_nested():
while True:
yield IT.chain(infinitely_nested(), IT.repeat(1))
print(list(IT.islice(flatten(infinitely_nested()), 10)))
# hangs
Voici ma version fonctionnelle de aplatissement récursif, qui gère à la fois les nuplets et les listes, et vous permet d'ajouter n'importe quel mélange d'arguments de position. Retourne un générateur qui produit la séquence complète dans l'ordre, arg par arg:
flatten = lambda *n: (e for a in n
for e in (flatten(*a) if isinstance(a, (Tuple, list)) else (a,)))
Usage:
l1 = ['a', ['b', ('c', 'd')]]
l2 = [0, 1, (2, 3), [[4, 5, (6, 7, (8,), [9]), 10]], (11,)]
print list(flatten(l1, -2, -1, l2))
['a', 'b', 'c', 'd', -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
Voici une autre réponse encore plus intéressante ...
import re
def Flatten(TheList):
a = str(TheList)
b,crap = re.subn(r'[\[,\]]', ' ', a)
c = b.split()
d = [int(x) for x in c]
return(d)
Fondamentalement, il convertit la liste imbriquée en chaîne, utilise une expression rationnelle pour supprimer la syntaxe imbriquée, puis reconvertit le résultat en une liste (aplatie).
def flatten(xs):
res = []
def loop(ys):
for i in ys:
if isinstance(i, list):
loop(i)
else:
res.append(i)
loop(xs)
return res
Vous pouvez utiliser deepflatten
du package tiers iteration_utilities
:
>>> from iteration_utilities import deepflatten
>>> L = [[[1, 2, 3], [4, 5]], 6]
>>> list(deepflatten(L))
[1, 2, 3, 4, 5, 6]
>>> list(deepflatten(L, types=list)) # only flatten "inner" lists
[1, 2, 3, 4, 5, 6]
C'est un itérateur, vous devez donc l'itérer (par exemple en l'enveloppant avec list
ou en l'utilisant dans une boucle). En interne, il utilise une approche itérative au lieu d'une approche récursive. Il est écrit en tant qu'extension C et peut donc être plus rapide que les approches python pures:
>>> %timeit list(deepflatten(L))
12.6 µs ± 298 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
>>> %timeit list(deepflatten(L, types=list))
8.7 µs ± 139 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
>>> %timeit list(flatten(L)) # Cristian - Python 3.x approach from https://stackoverflow.com/a/2158532/5393381
86.4 µs ± 4.42 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> %timeit list(flatten(L)) # Josh Lee - https://stackoverflow.com/a/2158522/5393381
107 µs ± 2.99 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> %timeit list(genflat(L, list)) # Alex Martelli - https://stackoverflow.com/a/2159079/5393381
23.1 µs ± 710 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Je suis l'auteur de la bibliothèque iteration_utilities
.
C'était amusant d'essayer de créer une fonction qui pouvait aplatir une liste irrégulière en Python, mais bien sûr, c'est à cela que sert Python (pour rendre la programmation amusante). Le générateur suivant fonctionne assez bien avec quelques mises en garde:
def flatten(iterable):
try:
for item in iterable:
yield from flatten(item)
except TypeError:
yield iterable
Il va aplatir les types de données que vous voudrez peut-être laisser seuls (tels que les objets bytearray
, bytes
et str
). En outre, le code repose sur le fait que demander un itérateur à un non-itérable soulève une TypeError
.
>>> L = [[[1, 2, 3], [4, 5]], 6]
>>> def flatten(iterable):
try:
for item in iterable:
yield from flatten(item)
except TypeError:
yield iterable
>>> list(flatten(L))
[1, 2, 3, 4, 5, 6]
>>>
Modifier:
Je ne suis pas d'accord avec la mise en œuvre précédente. Le problème est que vous ne devriez pas être en mesure d’aplatir quelque chose qui n’est pas itérable. C'est déroutant et donne une fausse impression de l'argument.
>>> list(flatten(123))
[123]
>>>
Le générateur suivant est presque identique au premier mais n’a pas le problème de vouloir aplatir un objet non-itérable. Il échoue comme on pourrait s'y attendre lorsqu'un argument inapproprié lui est donné.
def flatten(iterable):
for item in iterable:
try:
yield from flatten(item)
except TypeError:
yield item
Tester le générateur fonctionne bien avec la liste fournie. Cependant, le nouveau code générera une TypeError
lorsqu'un objet non-iterable lui est donné. Des exemples sont présentés ci-dessous du nouveau comportement.
>>> L = [[[1, 2, 3], [4, 5]], 6]
>>> list(flatten(L))
[1, 2, 3, 4, 5, 6]
>>> list(flatten(123))
Traceback (most recent call last):
File "<pyshell#32>", line 1, in <module>
list(flatten(123))
File "<pyshell#27>", line 2, in flatten
for item in iterable:
TypeError: 'int' object is not iterable
>>>
Bien qu'une réponse élégante et très Pythonique ait été sélectionnée, je présenterais ma solution uniquement pour l'examen:
def flat(l):
ret = []
for i in l:
if isinstance(i, list) or isinstance(i, Tuple):
ret.extend(flat(i))
else:
ret.append(i)
return ret
S'il vous plaît dites à quel point ce code est bon ou mauvais?
Voici une fonction simple qui aplatit les listes de profondeur arbitraire. Pas de récursivité, pour éviter le débordement de pile.
from copy import deepcopy
def flatten_list(nested_list):
"""Flatten an arbitrarily nested list, without recursion (to avoid
stack overflows). Returns a new list, the original list is unchanged.
>> list(flatten_list([1, 2, 3, [4], [], [[[[[[[[[5]]]]]]]]]]))
[1, 2, 3, 4, 5]
>> list(flatten_list([[1, 2], 3]))
[1, 2, 3]
"""
nested_list = deepcopy(nested_list)
while nested_list:
sublist = nested_list.pop(0)
if isinstance(sublist, list):
nested_list = sublist + nested_list
else:
yield sublist
Je préfère les réponses simples. Pas de générateurs. Aucune récursion ou limite de récursivité. Juste itération:
def flatten(TheList):
listIsNested = True
while listIsNested: #outer loop
keepChecking = False
Temp = []
for element in TheList: #inner loop
if isinstance(element,list):
Temp.extend(element)
keepChecking = True
else:
Temp.append(element)
listIsNested = keepChecking #determine if outer loop exits
TheList = Temp[:]
return TheList
Cela fonctionne avec deux listes: une boucle for interne et une boucle while externe.
La boucle for interne parcourt la liste. S'il trouve un élément de la liste, il (1) utilise list.extend () pour aplatir le niveau d'imbrication de la première partie et (2) rétablit keepChecking à True. Keepchecking est utilisé pour contrôler la boucle while externe. Si la boucle externe est définie sur true, elle déclenche la boucle interne pour une autre passe.
Ces passes continuent jusqu'à ce qu'il n'y ait plus de listes imbriquées. Lorsqu'une passe survient enfin sans trouver d'objet, keepChecking n'est jamais déclenchée à true, ce qui signifie que listIsNested reste false et que la boucle while externe se ferme.
La liste aplatie est ensuite renvoyée.
Essai
flatten([1,2,3,4,[100,200,300,[1000,2000,3000]]])
[1, 2, 3, 4, 100, 200, 300, 1000, 2000, 3000]
Voici l'implémentation compiler.ast.flatten
dans 2.7.5:
def flatten(seq):
l = []
for elt in seq:
t = type(elt)
if t is Tuple or t is list:
for elt2 in flatten(elt):
l.append(elt2)
else:
l.append(elt)
return l
Il existe de meilleures méthodes plus rapides (si vous êtes arrivé ici, vous les avez déjà vues)
Notez aussi:
Déconseillé depuis la version 2.6: Le package du compilateur a été supprimé de Python 3.
Je n'ai pas passé en revue toutes les réponses déjà disponibles, mais voici un modèle que j'ai proposé, empruntant à la méthode de traitement des listes LISP et de la liste de repos du LISP.
def flatten(l): return flatten(l[0]) + (flatten(l[1:]) if len(l) > 1 else []) if type(l) is list else [l]
voici un cas simple et un cas pas si simple -
>>> 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]
>>>
Je suis surpris que personne n'y ait pensé. Putain de récursion Je ne reçois pas les réponses récursives que les gens avancés ont données ici. de toute façon voici ma tentative sur ce point. l'avertissement est qu'il est très spécifique au cas d'utilisation du PO
import re
L = [[[1, 2, 3], [4, 5]], 6]
flattened_list = re.sub("[\[\]]", "", str(L)).replace(" ", "").split(",")
new_list = list(map(int, flattened_list))
print(new_list)
sortie:
[1, 2, 3, 4, 5, 6]
Le moyen le plus simple consiste à utiliser la bibliothèque morph en utilisant pip install morph
.
Le code est:
import morph
list = [[[1, 2, 3], [4, 5]], 6]
flattened_list = morph.flatten(list) # returns [1, 2, 3, 4, 5, 6]
totalement hacky mais je pense que cela fonctionnerait (en fonction de votre type de données)
flat_list = ast.literal_eval("[%s]"%re.sub("[\[\]]","",str(the_list)))
Voici une autre approche py2, je ne sais pas si c'est la plus rapide, la plus élégante ou la plus sûre ...
from collections import Iterable
from itertools import imap, repeat, chain
def flat(seqs, ignore=(int, long, float, basestring)):
return repeat(seqs, 1) if any(imap(isinstance, repeat(seqs), ignore)) or not isinstance(seqs, Iterable) else chain.from_iterable(imap(flat, seqs))
Il peut ignorer tout type spécifique (ou dérivé) de votre choix, il retourne un itérateur, vous pouvez donc le convertir en un conteneur spécifique tel que list, Tuple, dict ou simplement le consommer afin de réduire l'encombrement mémoire, pour le meilleur ou pour le pire. il peut gérer des objets initiaux non-itérables tels que int ...
Notez que la plupart des tâches lourdes se font en C, car, autant que je sache, comment les outils sont implémentés, alors, bien que ce soit récursif, autant que je sache, il n’est pas limité par la profondeur de récursivité de python ne signifie pas que vous êtes limité par la mémoire, spécialement sous OS X où la taille de sa pile a une limite stricte à compter d'aujourd'hui (OS X Mavericks) ...
il existe une approche légèrement plus rapide, mais moins portable, utilisez-la uniquement si vous pouvez supposer que les éléments de base de l'entrée peuvent être explicitement déterminés, sinon vous obtiendrez une récursion infinie, et OS X avec sa taille de pile limitée jeter une faute de segmentation assez rapidement ...
def flat(seqs, ignore={int, long, float, str, unicode}):
return repeat(seqs, 1) if type(seqs) in ignore or not isinstance(seqs, Iterable) else chain.from_iterable(imap(flat, seqs))
ici, nous utilisons des ensembles pour vérifier le type, il faut donc O(1) vs O (nombre de types) pour vérifier si un élément doit être ignoré, bien que toute valeur avec un type dérivé du type indiqué les types ignorés échouent, c’est pourquoi il utilise str
, unicode
alors utilisez-le avec prudence ...
tests:
import random
def test_flat(test_size=2000):
def increase_depth(value, depth=1):
for func in xrange(depth):
value = repeat(value, 1)
return value
def random_sub_chaining(nested_values):
for values in nested_values:
yield chain((values,), chain.from_iterable(imap(next, repeat(nested_values, random.randint(1, 10)))))
expected_values = Zip(xrange(test_size), imap(str, xrange(test_size)))
nested_values = random_sub_chaining((increase_depth(value, depth) for depth, value in enumerate(expected_values)))
assert not any(imap(cmp, chain.from_iterable(expected_values), flat(chain(((),), nested_values, ((),)))))
>>> test_flat()
>>> list(flat([[[1, 2, 3], [4, 5]], 6]))
[1, 2, 3, 4, 5, 6]
>>>
$ uname -a
Darwin Samys-MacBook-Pro.local 13.3.0 Darwin Kernel Version 13.3.0: Tue Jun 3 21:27:35 PDT 2014; root:xnu-2422.110.17~1/RELEASE_X86_64 x86_64
$ python --version
Python 2.7.5
Je suis conscient qu'il y a déjà beaucoup de réponses géniales mais je voulais ajouter une réponse qui utilise la méthode de programmation fonctionnelle pour résoudre la question. Dans cette réponse, je me sers de la double récursivité:
def flatten_list(seq):
if not seq:
return []
Elif isinstance(seq[0],list):
return (flatten_list(seq[0])+flatten_list(seq[1:]))
else:
return [seq[0]]+flatten_list(seq[1:])
print(flatten_list([1,2,[3,[4],5],[6,7]]))
sortie:
[1, 2, 3, 4, 5, 6, 7]
Je ne suis pas sûr que ce soit nécessairement plus rapide ou plus efficace, mais voici ce que je fais:
def flatten(lst):
return eval('[' + str(lst).replace('[', '').replace(']', '') + ']')
L = [[[1, 2, 3], [4, 5]], 6]
print(flatten(L))
La fonction flatten
transforme ici la liste en une chaîne, supprime tous des crochets, rattache les crochets aux extrémités et la reconstitue en liste.
Cependant, si vous saviez que vous aviez des crochets dans votre liste, tels que [[1, 2], "[3, 4] and [5]"]
, vous auriez à faire autre chose.
Utiliser itertools.chain
:
import itertools
from collections import Iterable
def list_flatten(lst):
flat_lst = []
for item in itertools.chain(lst):
if isinstance(item, Iterable):
item = list_flatten(item)
flat_lst.extend(item)
else:
flat_lst.append(item)
return flat_lst
Ou sans chaînage:
def flatten(q, final):
if not q:
return
if isinstance(q, list):
if not isinstance(q[0], list):
final.append(q[0])
else:
flatten(q[0], final)
flatten(q[1:], final)
else:
final.append(q)
Il suffit d'utiliser une bibliothèque funcy
: pip install funcy
import funcy
funcy.flatten([[[[1, 1], 1], 2], 3]) # returns generator
funcy.lflatten([[[[1, 1], 1], 2], 3]) # returns list
J'ai utilisé récursif pour résoudreliste imbriquée avec une profondeur
def combine_nlist(nlist,init=0,combiner=lambda x,y: x+y):
'''
apply function: combiner to a nested list element by element(treated as flatten list)
'''
current_value=init
for each_item in nlist:
if isinstance(each_item,list):
current_value =combine_nlist(each_item,current_value,combiner)
else:
current_value = combiner(current_value,each_item)
return current_value
Donc, après avoir défini la fonction combine_nlist, il est facile d’utiliser cette fonction pour mettre à plat. Ou vous pouvez le combiner en une seule fonction. J'aime ma solution car elle peut être appliquée à n'importe quelle liste imbriquée.
def flatten_nlist(nlist):
return combine_nlist(nlist,[],lambda x,y:x+[y])
résultat
In [379]: flatten_nlist([1,2,3,[4,5],[6],[[[7],8],9],10])
Out[379]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Cette solution peut fonctionner avec tous les objets sauf str et bytes.
from collections import Iterable
from collections import Iterator
def flat_iter(obj):
stack = [obj]
while stack:
element = stack.pop()
if element and isinstance(element, Iterator):
stack.append(element)
try:
stack.append(next(element))
except StopIteration:
stack.pop()
Elif isinstance(element, Iterable) and not isinstance(element, (str, bytes)):
stack.append(iter(element))
else:
yield element
tree_list = [[(1,2,3),(4,5,6, (7,8, 'next element is 5')), (5,6), [[[3,4,5],'foo1'],'foo2'],'foo3']]
not_iterable = 10
it1 = flat_iter(tree_list)
it2 = flat_iter(not_iterable)
print(list(it1))
print(list(it2))
[1, 2, 3, 4, 5, 6, 7, 8, 'le prochain élément est 5', 5, 6, 3, 4, 5, 'foo1', 'foo2', 'foo3']
[dix]
c'est peut-être une vieille question, je voudrais tenter le coup.
Je suis un idiot alors je vais donner une solution "idiote". toute cette récursion me fait mal au cerveau.
flattened_list = []
nested_list =[[[1, 2, 3], [4, 5]], 6]
def flatten(nested_list, container):
for item in nested_list:
if isintance(item, list):
flatten(item)
else:
container.append(i)
>>> flatten(nested_list, flattened_list)
>>> flattened_list
[1, 2, 3, 4, 5, 6]
Je comprends qu’il utilise un effet secondaire, mais c’est au mieux de ma compréhension de la récursivité qui peut aller
Je ne vois rien de ce genre posté ici et venant d'une question fermée sur le même sujet, mais pourquoi ne pas simplement faire quelque chose comme ceci (si vous connaissez le type de la liste que vous voulez séparer):
>>> a = [1, 2, 3, 5, 10, [1, 25, 11, [1, 0]]]
>>> g = str(a).replace('[', '').replace(']', '')
>>> b = [int(x) for x in g.split(',') if x.strip()]
Vous auriez besoin de connaître le type des éléments, mais je pense que cela peut être généralisé et je pense que ce serait plus rapide.
Pas de récursivité ni de boucles imbriquées. Quelques lignes. Bien formaté et facile à lire:
def flatten_deep(arr: list):
""" Flattens arbitrarily-nested list `arr` into single-dimensional. """
while arr:
if isinstance(arr[0], list): # Checks whether first element is a list
arr = arr[0] + arr[1:] # If so, flattens that first element one level
else:
yield arr.pop(0) # Otherwise yield as part of the flat array
flatten_deep(L)
À partir de mon propre code sur https://github.com/jorgeorpinel/flatten_nested_lists/blob/master/flatten.py
Ceci est un simple outil d'aplatissement sur python2
flatten=lambda l: reduce(lambda x,y:x+y,map(flatten,l),[]) if isinstance(l,list) else [l]
test=[[1,2,3,[3,4,5],[6,7,[8,9,[10,[11,[12,13,14]]]]]],]
print flatten(test)
#output [1, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
Sans utiliser aucune bibliothèque:
def flat(l):
def _flat(l, r):
if type(l) is not list:
r.append(l)
else:
for i in l:
r = r + flat(i)
return r
return _flat(l, [])
# example
test = [[1], [[2]], [3], [['a','b','c'] , [['z','x','y']], ['d','f','g']], 4]
print flat(test) # prints [1, 2, 3, 'a', 'b', 'c', 'z', 'x', 'y', 'd', 'f', 'g', 4]
Cela aplatira une liste ou un dictionnaire (ou une liste de listes ou de dictionnaires de dictionnaires, etc.). Il suppose que les valeurs sont des chaînes et crée une chaîne qui concatène chaque élément avec un argument de séparation. Si vous le souhaitez, vous pouvez utiliser le séparateur pour scinder ultérieurement le résultat en un objet de liste. Il utilise la récursivité si la valeur suivante est une liste ou une chaîne. Utilisez l'argument key pour indiquer si vous voulez les clés ou les valeurs (définir key sur false) de l'objet dictionnaire.
def flatten_obj(n_obj, key=True, my_sep=''):
my_string = ''
if type(n_obj) == list:
for val in n_obj:
my_sep_setter = my_sep if my_string != '' else ''
if type(val) == list or type(val) == dict:
my_string += my_sep_setter + flatten_obj(val, key, my_sep)
else:
my_string += my_sep_setter + val
Elif type(n_obj) == dict:
for k, v in n_obj.items():
my_sep_setter = my_sep if my_string != '' else ''
d_val = k if key else v
if type(v) == list or type(v) == dict:
my_string += my_sep_setter + flatten_obj(v, key, my_sep)
else:
my_string += my_sep_setter + d_val
Elif type(n_obj) == str:
my_sep_setter = my_sep if my_string != '' else ''
my_string += my_sep_setter + n_obj
return my_string
return my_string
print(flatten_obj(['just', 'a', ['test', 'to', 'try'], 'right', 'now', ['or', 'later', 'today'],
[{'dictionary_test': 'test'}, {'dictionary_test_two': 'later_today'}, 'my power is 9000']], my_sep=', ')
rendements:
juste, un test, pour, essayer, bon, maintenant, ou, plus tard, aujourd'hui, dictionary_test, dictionary_test_two, mon pouvoir est de 9000
Je suis nouveau sur python et viens d'un fond de LISP. C’est ce que j’ai trouvé (regardez les noms de var pour lulz):
def flatten(lst):
if lst:
car,*cdr=lst
if isinstance(car,(list,Tuple)):
if cdr: return flatten(car) + flatten(cdr)
return flatten(car)
if cdr: return [car] + flatten(cdr)
return [car]
Semble travailler. Tester:
flatten((1,2,3,(4,5,6,(7,8,(((1,2)))))))
résultats:
[1, 2, 3, 4, 5, 6, 7, 8, 1, 2]
Python-3
from collections import Iterable
L = [[[1, 2, 3], [4, 5]], 6,[7,[8,9,[10]]]]
def flatten(thing):
result = []
if isinstance(thing, Iterable):
for item in thing:
result.extend(flatten(item))
else:
result.append(thing)
return result
flat = flatten(L)
print(flat)
Nous pouvons également utiliser la fonction 'type' de python. Lors de l'itération de la liste, nous vérifions si l'élément est une liste ou non. Sinon, nous "ajoutons", sinon nous "l'étendrons". Voici un exemple de code -
l=[1,2,[3,4],5,[6,7,8]]
x=[]
for i in l:
if type(i) is list:
x.extend(i)
else:
x.append(i)
print x
Sortie:
[1, 2, 3, 4, 5, 6, 7, 8]
Pour plus d'informations sur append () et extend (), consultez le site Web suivant: https://docs.python.org/2/tutorial/datastructures.html
Similaire à la réponse de diligar
weird_list=[[1, 2, 3], [4, 5, 6], [7], [8, 9]]
Nice_list = list(map(int, ''.join([e for e in str(weird_list) if e not in '[ ]']).split(',')))
De mon réponse précédente , cette fonction aplatit la plupart des cas auxquels je peux penser. Je crois que cela fonctionne en python 2.3.
def flatten(item, keepcls=(), keepobj=()):
if not hasattr(item, '__iter__') or isinstance(item, keepcls) or item in keepobj:
yield item
else:
for i in item:
for j in flatten(i, keepcls, keepobj + (item,)):
yield j
Listes circulaires
>>> list(flatten([1, 2, [...], 3]))
[1, 2, [1, 2, [...], 3], 3]
Depth premières listes
>>> list(flatten([[[1, 2, 3], [4, 5]], 6]))
[1, 2, 3, 4, 5, 6]
Listes répétées imbriquées:
>>> list(flatten([[1,2],[1,[1,2]],[1,2]]))
[1, 2, 1, 1, 2, 1, 2]
Listes avec des dicts (ou d'autres objets à ne pas aplatir)
>>> list(flatten([1,2, {'a':1, 'b':2}, 'text'], keepcls=(dict, str)))
[1, 2, {'a': 1, 'b': 2}, 'text']
Tous les iterables
>>> list(flatten((x for x in [1,2, set([3,(4,5),6])])))
[1, 2, 4, 5, 3, 6]
Vous voudrez peut-être conserver certaines classes par défaut dans
keepcls
pour pouvoir appeler la fonction plus laconique.
Si vous aimez la récursion, cette solution pourrait vous intéresser:
def f(E):
if E==[]:
return []
Elif type(E) != list:
return [E]
else:
a = f(E[0])
b = f(E[1:])
a.extend(b)
return a
En fait, j'ai adapté cela à partir d'un code de schéma de pratique que j'avais écrit il y a longtemps.
Prendre plaisir!
Tiré sans vergogne de ma propre réponse à une autre question .
Cette fonction
isinstance
, parce que c'est diabolique et empêche la dactylographie.reduce
récursivement. Il doit y avoir une réponse utilisant reduce
.Code ci-dessous:
def flattener(left, right):
try:
res = reduce(flattener, right, left)
except TypeError:
left.append(right)
res = left
return res
def flatten(seq):
return reduce(flattener, seq, [])
>>> nested_list = [0, [1], [[[[2]]]],
[3, [], [4, 5]],
[6, [7, 8],
9, [[[]], 10,
[]]],
11, [], [],
[12]]
>>> flatten(nested_list)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]