Quelle est la façon dont la méthode recommandée aplatit les listes imbriquées depuis le Déprécation du compilateur paquet ?
>>> from compiler.ast import flatten >>> flatten(["junk",["nested stuff"],[],[[]]]) ['junk', 'nested stuff']
7 Réponses :
ithertools.chain code>
est la meilleure solution pour APPATTEZ TOUT NIVEUR DIRECTÉ NETHABLE - Il est très efficace par rapport à toute solution pure-python.
qui dit, il fonctionnera sur tous em> itérables, donc une vérification est requise si vous voulez éviter d'éviter l'aplatissement Les cordes, par exemple. P> De même, il ne sera pas aplué comme par magie à une profondeur arbitraire. Cela dit, de manière générale, une telle solution générique n'est pas nécessaire - mais il est préférable de conserver vos données structurées de manière à ce qu'elle ne nécessite pas d'aplativement de cette manière. P> Edit: Je dirais que si l'on avait Pour faire un aplatissement arbitraire, c'est la meilleure façon: p> N'oubliez pas d'utiliser Comme indiqué dans les commentaires Je dirais que ceci est l'option nucléaire et est susceptible de causer plus de problèmes que ce qu'il résoue. Au lieu de cela, la meilleure idée est de rendre votre sortie plus régulière (sortie contenant un élément qui lui donne toujours un tuple d'un élément, par exemple), et effectuez un aplatissement régulier d'un niveau où il est introduit, plutôt que tout à la fin. P> Cela produira plus logique, lisible et plus facile à travailler avec le code. Naturellement, il y a des cas où vous besoin em> pour faire ce genre d'aplatissement (si les données proviennent d'une part, vous ne pouvez pas vous gâcher, vous n'avez donc aucune option mais de le prendre dans le mal structuré Format), auquel cas, ce type de solution pourrait être nécessaire, mais en général, c'est probablement une mauvaise idée. P> P> bastion code> in 2.x sur
str code> et
pour subel in aplatiss (EL): rendement el code> au lieu de
du rendement de flatten (el) code> pré-3.3. p>
Merci. Cela peut être une clarification idiote, mais avez-vous une recommandation pour comment le banaliser? >>> iTERTOOLS.CHAIN ([[["DOWN", ["Stuff imbriqué"], [], [], []]])
Unitée i>? Je ne suis pas vraiment sûr de quoi cela signifie vouloir dire. Liste (iTABLE) CODE> est le meilleur moyen d'obtenir une liste d'un arbitraire itérable.
Utilisation de la liste ci-dessus, je reçois: >>> Liste (itheroTools.chain ([[[["Junk», ["Stuff imbriqué"], [], [],]])) code> < Code> [["Junk ', [" Stuff imbribés "], [], [], [[]]]]] code> contre
aplatissé () code> qui donne
[' Junk ',' Stuff imbriqués '] code>
Chaîne () CODE> Demoise une ierérable en tant qu'argument, si vous souhaitez transmettre une iérente, utilisez
chaîne.from_iterable () code>. Notez qu'il sera (comme indiqué dans la réponse) enlevez uniquement une couche de nidification. Au-delà, cela ne vaut pas vraiment la peine de faire un outil générique, car différentes situations traiteront des itérables différents comme ayant besoin d'être aplati (par exemple, des chaînes).
Désolé, je ne suis peut-être pas toujours en train de ne pas l'obtenir: >>> (iTERTOOLS.CHAIN.FROM_ITERABLE ([["DOWN", ["Stuff imbriqué"], [], []]])) / code> me donne
['Junk', ['Stuff imbriquée'], [], [[]]] code>
@Imitchops Oui, il a supprimé une couche de nidification - la liste extérieure (qui ne contient qu'un seul article).
Hmm, mais si j'essaie d'inhormir cela en aplatissant à nouveau, je reçois ceci: >>> Liste (itheroTools.chain.from_iterable (ithertools.chain.from_iter capable ([["Junk", ["Nid Ed Stuff "], [], [[]]]]]]))) code>
['J', 'U', 'N', 'K'," Stuff imbriqué ", []] code> qui n'est toujours pas plat et aussi très difficile à lire. = /
@ Mittenchops J'ai expliqué dans la réponse qu'elle aplatit des cordes (comme elles sont aussi propres aussi) et ne fonctionnent pas à une profondeur arbitraire. En général, l'option nucléaire aplatit des listes nichées arbitrairement et est susceptible de causer plus de problèmes que de résousts. Au lieu de cela, la meilleure idée est de rendre votre sortie plus régulière (sortie contenant un élément qui lui donne toujours un tuple d'un élément, par exemple), et effectuez un aplatissement régulier d'un niveau où il est introduit, plutôt que tout à la fin.
Votre fonction indiquée prend une liste imbriquée et aplatit dans une nouvelle liste.
Pour aplatir une liste arbitraire imbriquée dans une nouvelle liste, cela fonctionne sur Python 3, comme vous vous attendez: P>
def flat_gen(x): def iselement(e): return not(isinstance(e, collections.Iterable) and not isinstance(e, str)) for el in x: if iselement(el): yield el else: yield from flat_gen(el)
Construire une liste comme ceci est une solution vraiment mauvaise, un générateur serait beaucoup plus apte.
Je dirais que «vraiment mauvaise solution» est un peu fort. Si la liste imbriquée est relativement petite, la construction d'un générateur peut être plus lente. Cela dépend du besoin. J'ai posté les deux.
Il peut bien être plus lent de créer un générateur sur une petite liste, mais quand il est petit, la différence de temps ne va pas. Quand c'est grand, cependant, cela pourrait bien faire. Il est préférable de simplement utiliser le générateur, sans distinction, et c'est plus lisible. Au-delà de cela, hasattr (E, "__iter __") code> est généralement un chèque mieux fait en utilisant le
ibler code> abc - il est plus lisible de cette façon.
Il n'y a pas de méthode intégrée pour une liste avec une nicheuse arbitraire, mais quelque chose comme ça ... ... fonctionnera pour les listes et les tuples. Si vous souhaitez prendre en charge un objet que vous pouvez utiliser dans un ... qui est légèrement plus robuste que de vérifier pour l'élément dans l'objet d'objet code>, il est probablement préférable d'utiliser la typing de canard comme celle-ci ... p>
isinstance (el, iérhable) code>, car il ne gênera pas certains cas, tels que celui-ci ... P> < Pré> xxx pré> p>
-1 - Type de vérification des listes et des tuples rend cette extrêmement inflexible.
@Lattyware La question était la suivante: "Quelle est la façon recommandée de déployer des listes imbriquées ..."
@Lattyware Tout commentaire sur la deuxième option?
Désolé, je répondais sur ma propre question. Mon problème est que Python est une langue flexible et une vérification de type n'est qu'une solution généralement mauvaise. L'astucieux ne peut penser que des listes, mais à un moment donné, utilisez une structure de données personnalisée qui fonctionne comme une liste, mais ne fonctionnera pas avec votre code. Python est conçu pour la typage du canard, et donc des fonctions qui fonctionnent uniquement avec certains types, malgré les autres types capables sont très ennuyeux de travailler avec et généralement une mauvaise idée.
Quant à la deuxième méthode, ce n'est pas terrible (il est très similaire à l'option que j'ai donnée, sauf prend le Essayer / sauf code> sur la vérification à l'avance - ils sont très similaires, si la liste à aplatie A une proportion élevée des articles monocenseurs ou une forte proportion de itérables imbriquées, on pourrait être préférable, mais il est peu probable que cela importe. Comme je l'énonce dans ma réponse, je pense que la meilleure solution est de Éviter un besoin d'une telle fonction En premier lieu i>.
@Lattyware Eh bien, j'ai noté un inconvénient de votre option, mais c'est une sorte de cas de bord. Néanmoins, il semble un peu dure à bowervote pour la raison pour laquelle vous avez donné, en particulier, car cela ne s'applique plus.
Vérifiez votre compte vote, j'ai supprimé ce bowvote dès que vous avez ajouté l'alternative. Sur le cas de bord, oui, il existe un léger potentiel, mais en même temps, l'ABC pour itérables est clair, ils doivent mettre en œuvre __ iter __ () code>, donc je dirais que c'est plus un cas de La classe étant mal concevante si elle est censée être iérienne - j'ai vu des cas où
__ getItem __ () code> a été défini là où itérant les valeurs n'aurait pas de sens. C'est un cas rare, mais je dirais qu'il est difficile d'appeler ce que le comportement devrait être sur un objet comme celui-là.
@Lattyware Je me rappelle avoir une discussion similaire avec Martijn Pieters récemment, qui a suggéré d'utiliser isinstance (el, séquence) code> pour gérer le cas
___ getitem __ () code> cas, bien qu'il n'ait jamais été clair si Cela impliquait que la séquence
code> était un superset strict de
ibler code> ou s'il était tenu de tester les deux possibilités.
Je suis à peu près sûr que la séquence code> nécessite __ len __ () code> à définir et teste probablement son
ibler code> aussi.
@Lattyware a l'air d'avoir raison. Je pense que le point que j'essaie de faire est la distinction entre le terme "iThable" et "tout objet qui pourrait éventuellement être utilisé dans un pour l'élément dans l'objet code> expression". Donc, si, comme vous le dites, "Python est conçu pour la dactylographie du canard", aucune des catégories
Collections code> va aider, et le seul moyen réel d'être sûr est d'essayer le
pour < / Code> Boucle et attrapez l'exception si elle échoue.
My Ugly Solution de la chaîne Code> Juste pour le plaisir:
from collections import Iterable
from itertools import chain
def flatten3(seq, exclude=(str,)):
sub = iter(seq)
try:
while sub:
while True:
j = next(sub)
if not isinstance(j, Iterable) or isinstance(j, exclude):
yield j
else:
sub = chain(j, sub)
break
except StopIteration:
return
Vous pouvez utiliser Flatten fonction de Funcy bibliothèque: Vous pouvez également spécifier explicitement les valeurs à suivre: p> < Pré> xxx pré> jeter un coup d'œil sur Sa mise en œuvre si vous voulez un algorythm. p> p>
Je suis venu aimer beaucoup de funcy. Merci pour le conseil.
Construit pour la récursivité: Python 3.6
def flatten(lst): """Flattens a list of lists""" return [subelem for elem in lst for subelem in elem]
Juste une autre récursion: Python 3.6. Fonctionne bien pour une liste imbriquée complexe de listes / chaînes / chiffres et combinaison de tous: Voir l'exemple ci-dessous: p> >>> nestedList=['arash',[[1,'anotherOne',[12,'stringX',['kave']]], 'stringY']]
>>> list_flattener(nestedList)
['kave', 12, 'stringX', 1, 'anotherOne', 'stringY', 'arash']