Erlang et Ruby sont tous deux dotés de fonctions permettant d'aplatir les tableaux. Cela semble être un outil simple et utile à ajouter à une langue. On pourrait faire ceci:
>>> mess = [[1, [2]], 3, [[[4, 5]], 6]]
>>> mess.flatten()
[1, 2, 3, 4, 5, 6]
Ou même:
>>> import itertools
>>> mess = [[1, [2]], 3, [[[4, 5]], 6]]
>>> list(itertools.flatten(mess))
[1, 2, 3, 4, 5, 6]
Au lieu de cela, en Python, il faut passer par le problème d'écrire une fonction pour aplatir les tableaux. Cela me semble ridicule, l’aplanissement des tableaux est une chose si courante à faire. C'est comme avoir à écrire une fonction personnalisée pour concaténer deux tableaux.
J'ai googlé cela sans résultat, alors je demande ici; Y a-t-il une raison particulière pour laquelle un langage mature comme Python 3, qui contient cent mille piles différentes, ne fournit pas une méthode simple pour aplatir les tableaux? L'idée d'inclure une telle fonction a-t-elle été discutée et rejetée à un moment donné?
la source
extend
mais aplatir aurait été beaucoup plus élégant. Cependant, je suis blessé si ce motif est assez commun pour justifier un aplatissement dans la bibliothèque standard.Réponses:
Les propositions d’
flatten
ajout d’ une fonction à la bibliothèque standard apparaissent de temps en temps sur les listes de diffusion python-dev et python-ideas . Les développeurs Python répondent généralement avec les points suivants:Une mise à niveau à un niveau (transformant un itérable d'iterables en un unique itérable) est une expression triviale d'une ligne
(x for y in z for x in y)
et, dans tous les cas, se trouve déjà dans la bibliothèque standard sous le nomitertools.chain.from_iterable
.Quels sont les cas d'utilisation pour un aplatissement multiniveau à usage général? Sont-ils vraiment assez convaincants pour que la fonction soit ajoutée à la bibliothèque standard?
Comment un utilisateur multiniveau polyvalent déciderait-il à quel moment l'aplatir et le moment de son départ? Vous pourriez penser qu’une règle du type "tout ce qui prend en charge l’interface itérable" fonctionnerait, mais cela entraînerait une boucle infinie
flatten('a')
.Voir par exemple Raymond Hettinger :
la source
flatten
peut être définie commelambda z: [x for y in z for x in y]
.flatten
méthode. L'implémentation de cette méthode doit faire appel de manière récursiveflatten
à son sous-composant, si l'objet est un composite. Malheureusement, autant que je sache, chaque valeur n'est pas un objet en Python. En Ruby, ça devrait marcher.Cela vient avec une telle méthode mais ça ne s'appelle pas aplatir. Cela s'appelle " chaîne ". Il retourne un itérateur sur lequel vous auriez alors besoin d'utiliser la fonction list () pour le transformer en liste. Si vous ne souhaitez pas utiliser de *, vous pouvez utiliser la deuxième version "from_iterator". Cela fonctionne de la même manière en Python 3. Il échouera si l'entrée de liste n'est pas une liste de listes.
Il y avait à une époque une méthode d' aplatissement dans le module compiler.ast, mais elle était déconseillée dans la version 2.6 puis supprimée dans la version 3.0. La récursion de profondeur arbitraire, nécessaire pour les listes imbriquées de manière arbitraire, ne fonctionne pas bien avec la profondeur de récursivité maximale conservatrice de Python. Le raisonnement en faveur de la suppression du compilateur était en grande partie dû au fait que c'était un désordre . Le compilateur a été transformé en ast mais aplati a été laissé derrière.
Une profondeur arbitraire peut être obtenue avec les tableaux de Numpy et l'aplatissement de cette bibliothèque.
la source
chain.from_iterator
fonction, comme vous le dites, ne peut être utilisé pour aplatir les listes en deux dimensions. Une fonction d'aplatissement actuelle , qui accepte n'importe quel nombre de listes imbriquées et renvoie une liste unidimensionnelle, serait toujours extrêmement utile dans de nombreux cas (du moins à mon avis)... peut-être parce que ce n'est pas si difficile d'en écrire un toi-même
... et ensuite aplatissez tout ce que vous voulez :)
la source