[Python] défaire une séquence de séquences

Fermé
Bob El Ahn Messages postés 42 Date d'inscription dimanche 27 février 2005 Statut Contributeur Dernière intervention 25 juillet 2007 - 25 sept. 2006 à 17:48
Bob El Ahn Messages postés 42 Date d'inscription dimanche 27 février 2005 Statut Contributeur Dernière intervention 25 juillet 2007 - 11 oct. 2006 à 18:17
Chers ccmistes,

Voilà une fonction que je livre au cas où elle peut aider. En fait, je ne me souviens plus pourquoi je l'ai écrite mais ça a mis du temps! J'ai un fichier avec plus d'une dizaine de variations qui ne fonctionnent pas..

Listit() prend une séquence en argument et retourne une liste avec tous les éléments de la séquence dans l'ordre. Si la séquence comportait des 'nested sequences' listit les sort.
def listit(seq):
    """Takes a nested seqence and returns a flat list."""
    flatlist=[]
    if seq:
        if type(seq[0]) == type([]):
            flatlist = listit(seq[0]) + listit(seq[1:])
        elif type(seq[0]) == type(()):
            flatlist = listit(seq[0]) + listit(seq[1:])
        else:
            flatlist = [seq[0]] + listit(seq[1:])
    return flatlist

exemple:
>>> l = [('a', 2), ('b', 5), ('t', 6), [1, 2, 'r', 89, 'hi'], (98, 23, ('i', 7))]
>>> listit(l)
>>> ['a', 2, 'b', 5, 't', 6, 1, 2, 'r', 89, 'hi', 98, 23, 'i', 7]


Voilà j'espère que ça peut être utile. J'ai pas testé extensivement donc si vous trouvez des exceptions: postez.

Sinon si vous connaissez mieux pour obtenir ce résultat, un truc qui pythonne grave quoi, faites m'en part!

On doit pouvoir ajouter un comportement pour les dictionnaires.

Autrement : if type(seq[0]) == type(()) or type([]): faisait en général tout planter. Euh, pourquoi?

Mir,

7 réponses

Bob El Ahn Messages postés 42 Date d'inscription dimanche 27 février 2005 Statut Contributeur Dernière intervention 25 juillet 2007 8
25 sept. 2006 à 17:51
Oups, la docstring n'est pas tout à fait juste. Enfin.
Mir,
0
Bob El Ahn Messages postés 42 Date d'inscription dimanche 27 février 2005 Statut Contributeur Dernière intervention 25 juillet 2007 8
27 sept. 2006 à 15:52
Tiens, en survolant le tutoriel de Guido je pense que je vais faire un tour du côté du module 'array'..

Mir,
0
Bob El Ahn Messages postés 42 Date d'inscription dimanche 27 février 2005 Statut Contributeur Dernière intervention 25 juillet 2007 8
11 oct. 2006 à 16:39
Tiens j'ai pensé à une autre méthode, pas très clean j'admet..
def listit(seq):
	flatlist = str(seq)
	flatlist = flatlist.replace("[",'')
	flatlist = flatlist.replace("]", '')
	flatlist = flatlist.replace("(",'')
	flatlist = flatlist.replace(")", '')
	flatlist = "[%s]" % flatlist
	return eval(flatlist)

Certes, c'est un peu jouer sur les mots mais..

J'ai essayé de faire ça avec expressions régulières mais faut que je révise parce que ca le faisait pas.

D'ailleurs doit surement y avoir plus efficace même avec les 'string methods'. M'enfin je trouve que ca pythonne un peu, un tout petit peu.. ;)

Mir,
0
sebsauvage Messages postés 32893 Date d'inscription mercredi 29 août 2001 Statut Modérateur Dernière intervention 21 octobre 2019 15 659
11 oct. 2006 à 17:29
Vive Google Code Search ;-)

l = [('a', 2), ('b', 5), ('t', 6), [1, 2, 'r', (897,777,888), 'hi'], (98, 23, ('i', 7))]

import types

def _flatten(L,a):
    for x in L:
        if type(x) in (types.ListType,types.TupleType): _flatten(x,a)
        else: a(x)

def flatten(L):
    '''recursively flatten the list or tuple L'''
    R = []
    _flatten(L,R.append)
    return R
    
print flatten(l)   



(Trouvé là)
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
sebsauvage Messages postés 32893 Date d'inscription mercredi 29 août 2001 Statut Modérateur Dernière intervention 21 octobre 2019 15 659
11 oct. 2006 à 17:33
Présenté comme ça, c'est un peu mieux:

import types

def flatten(L):
    '''Recursively flatten the list or tuple L.
       Shamelessly heavily inspired from ReportLab_1_20.tgz/reportlab_1_20/reportlab/lib/utils.py    
    '''
    def _flatten(L,a):
        for x in L:
            if type(x) in (types.ListType,types.TupleType): _flatten(x,a)
            else: a(x)
    R = []
    _flatten(L,R.append)
    return R
    
l = [('a', 2), ('b', 5), ('t', 6), [1, 2, 'r', (897,777,888), 'hi'], (98, 23, ('i', 7))]
print flatten(l) 


Ce qui donne: ['a', 2, 'b', 5, 't', 6, 1, 2, 'r', 897, 777, 888, 'hi', 98, 23, 'i', 7]

(Notez la possibilité de déclarer des fonctions locales en Python... très sympa !)
0
sebsauvage Messages postés 32893 Date d'inscription mercredi 29 août 2001 Statut Modérateur Dernière intervention 21 octobre 2019 15 659
11 oct. 2006 à 17:35
Par contre, je crois qu'il serait plus pythonique d'utiliser isinstance() plutôt que de comparer les type().
0
Bob El Ahn Messages postés 42 Date d'inscription dimanche 27 février 2005 Statut Contributeur Dernière intervention 25 juillet 2007 8
11 oct. 2006 à 18:17
Merci pour cet exemple, c'est une fonction bien plus élégante que la mienne. Et en plus elle fait pas planter idle/python pour des listes un peu longues..

Faut que j'essaie de comparer la fonction récursive et la fonction 'texte'.. M'enfin j'ai pas encore eu à m'en servir ;)

Mir,
0