Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Mais aussi sur les technos front comme React, Angular, Typescript et Javascript en général.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

listes en python3

–1 vote

j'ai :

[
    [('01', 'Observatoire du logement aidé'), 
        [('01', 'Note méthodologique')], 
        [('02', '2 publications analysant 2 variables clés (+ traitements variables)'), 
            [('01', 'test')]
        ]
    ]
]

et je voudrais :

[   
    [('01', 'Observatoire du logement aidé'), ('01', 'Note méthodologique'), ()],
    [('01', 'Observatoire du logement aidé'), ('02', '2 publications analysant 2 variables clés (+ traitements variables)'), ('01', 'test')]
]

j'ai :

[
    [('01', 'Conséquence des évolutions numériques sur la mobilité'), 
        [('01', 'Note')]
    ], 
    [('02', 'Comparaison des coûts de la mobilité'), 
        [('01', 'Note')]
    ], 
    [('03', 'Alternatives à la mobilité automobile '), 
        [('01', 'Note')]
    ]
]

et je voudrais :

[   
    [('01', 'Conséquence des évolutions numériques sur la mobilité'), ('01', 'Note')],
    [('02', 'Comparaison des coûts de la mobilité'), ('01', 'Note')],
    [('03', 'Alternatives à la mobilité automobile '), ('01', 'Note')]
]
demandé il y a 6 jours par bidochon (186 points)
edité il y a 6 jours par lucas

Tu nous a pris pour ta gonzesse ? Monsieur «je veux» qui ne sait pas dire bonjour !
C'est le genre de question qui me gonfle.

Bonjour DoubleNain,

apparemment tu n'as jamais posé de question, car si tu l'avais fais tu aurais lu
ceci en gras et gros à ce moment la.

Votre question doit poser sur un problème lié au language PYTHON ou JAVASCRIPT Ainsi qu'aux Framework relatifs tels que Django, Flask, Bottle, React, Angular, Typescript, etc

Inutile de mettre "hello", "merci", etc. Juste la question suffit. Cela permet d'aller droit au but.
Ecrivez en bon Français sans abréviation!

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

si tu viens ici, pour la gloire et perdre ton temps à ce genre de commentaire, c'est que tu as surement plein de question à lire pour pourrir tous le monde.

par contre je t'assures que ma mère m'as bien élevé et que je t'aurais remercier, si tu avais pu m'aider.

si tu es si aigri, essaie de te faire aidé, si tu veux je peux t'écouter. si tu n'as personne à qui parler.

bon courage

@bidochon

Tu remarqueras que j'ai répondu à davantage de questions que j'en ai posées...

«si tu viens ici, pour la gloire et perdre ton temps à ce genre de commentaire, c'est que tu as surement plein de question à lire pour pourrir tous le monde.»

Je suis ici depuis plus longtemps que toi cher enfant ;), alors mon petit gars, va moucher ton nez ;)

«si tu es si aigri, essaie de te faire aidé, si tu veux je peux t'écouter. si tu n'as personne à qui parler.»

Et puisque tu sembles aimer donner des conseils, je ne t'en donne qu'un : apprends à rédiger correctement en français avant d'essayer de rédiger correctement en Python.

Allez, je te laisse, c'est bientôt l'heure de ton goûter ;) !

@bidochon ça marche pour le deuxième cas : désolé j'avais pas vu le premier. Cela dit, avec une imbrication pareille, je pense que tu devrais
retravailler le code à la source plutot si tu peux : tu as le code d'origine ?

2 Réponses

+1 vote
 
Meilleure réponse

Bon, c'est pas super beau mais ça fait le travail. Je pense que c'est un bon début, avec l'aide de la communauté il y aura éventuellement moyen d'améliorer les fonctions.

Cette fonction semble fonctionner de manière générique pour le premier cas (avec un nombre de sous-listes dynamique) :

def flatten(sequence):
    from itertools import repeat, zip_longest

    def flat(seq):
        if not seq:
            yield None
        else:
            if isinstance(seq, tuple):
                yield seq
            else:
                yield from flat(seq.pop(0))
                yield from flat(seq)

    def group(header, seq, n_fields, default=()):
        ret = []
        for line in flat(seq):
            if line:
                ret.append(line)
            elif ret:
                while len(ret) < n_fields - 1:
                    ret.append(default)
                yield [header, *ret]
                ret = []

    # https://stackoverflow.com/a/6039138/1117028
    depth = lambda L: isinstance(L, list) and max(map(depth, L)) + 1

    header, *lines = sequence[0]
    n_fields = depth(lines)
    return group(header, lines, n_fields)

Réponse originale :

def flatten1(seq):
    # Cas n°1
    header, *lines = seq[0]
    n_fields = len(max(lines))
    for line in lines:
        if len(line) < n_fields:
            yield [header, *line, ()]
        else:
            yield [header, line[0], *line[1]]


def flatten2(seq):
    # Cas n°2
    for line in seq:
        yield [line[0], *line[1]]

Pour tester :

a = [
    [('01', 'Observatoire du logement aidé'),
        [('01', 'Note méthodologique')],
        [('02', '2 publications analysant 2 variables clés (+ traitements variables)'),
            [('01', 'test')]
        ]
    ]
]
a_ok = [
    [('01', 'Observatoire du logement aidé'), ('01', 'Note méthodologique'), ()],
    [('01', 'Observatoire du logement aidé'), ('02', '2 publications analysant 2 variables clés (+ traitements variables)'), ('01', 'test')]
]
a_flat = list(flatten1(a))
assert a_ok == a_flat

b = [
    [('01', 'Conséquence des évolutions numériques sur la mobilité'),
        [('01', 'Note')]
    ],
    [('02', 'Comparaison des coûts de la mobilité'),
        [('01', 'Note')]
    ],
    [('03', 'Alternatives à la mobilité automobile '),
        [('01', 'Note')]
    ]
]
b_ok = [
    [('01', 'Conséquence des évolutions numériques sur la mobilité'), ('01', 'Note')],
    [('02', 'Comparaison des coûts de la mobilité'), ('01', 'Note')],
    [('03', 'Alternatives à la mobilité automobile '), ('01', 'Note')]
]
b_flat = list(flatten2(b))
assert b_ok == b_flat

Note pour plus tard : quand tu postes une question, c'est bien d'avoir quelques morceaux de code que tu as pu tester avant et d'enjoliver un peu la demande ;).

répondu il y a 4 jours par Tiger-222 (628 points)
edité il y a 3 jours par Tiger-222
peut on ajouter une gestion d'exception, pour être générique?

tout dabord, un grand merci.

Le contexte initial, est que j'ai une table postgresql, sur laquelle j'ai une foreign key sur elle même. Il faut que j'affiche toutes laisons sur une ligne, la profondeur, peut être différente en fonction des cas.

je récupère tous les enfants, par une requête postgresql :

    WITH RECURSIVE tree (id, ancestors, depth, cycle) AS (
        SELECT id, '{}'::integer[], 0, FALSE
        FROM projets_projet WHERE is_sub_of_id IS NULL
      UNION ALL
        SELECT
          n.id, t.ancestors || n.is_sub_of_id, t.depth + 1,
          n.is_sub_of_id = ANY(t.ancestors)
        FROM projets_projet n, tree t
        WHERE n.is_sub_of_id = t.id
        AND NOT t.cycle
    ) 
    SELECT n.num_string_projet, n.description, n.id, n.is_sub_of_id, p.classement
    FROM projets_projet n 
    INNER JOIN tree USING (id)
    INNER JOIN projets_typeprojet as p on n.type_projet_id = p.id
    WHERE %s = ANY(ancestors) AND n.axe_id = %s AND n.annee = %s AND n.is_sub_of_id = %s
    ORDER BY n.num_projet

Tes fonctions, fonctionnent parfaitement, mais il me faudrais qque chose de générique.

crois tu qu'un break en cas d'execption sur IndexError, pourrais faire l'affaire?

@bidochon, peux-tu copier/coller une exception complète que tu rencontres ?

en fait je n'en rencontre pas,
je me suis dis que je pourrais m'en servir pour sortir de la boucle plus tôt.

mais j'ai essayer et je n'y n'arrives pas

J'ai modifié la réponse avec une fonction générique.

MERCIIII

juste un petit soucis cela ne marche apparemment, que sur la première itération, j'ai l'impression que si la liste initiale à plus d'un élément, cela ne fonctionne pas.

pour le coût il suffit de vérifié si la longueur est > 1 et itérer dans un tel cas.

en tous cas tu viens de me sauver de bien des heures de recherches.

bon je viens d'essayeret même en itérant ça marche pas sur la deuxième

bon finalement cela marche si on applati la liste résultante de l'itération

def aplatliste(l):
    L = []
    for elem in l:
        if isinstance(elem, list):
            L.extend(aplatliste(elem))
        else:
            L.append(elem)
    return L

alors en fait le code global devient

def getprojet():
def get
child(p, a, annee):
l = []
sqlchild = """
WITH RECURSIVE tree (id, ancestors, depth, cycle) AS (
SELECT id, '{}'::integer[], 0, FALSE
FROM projets
projet WHERE issubofid IS NULL
UNION ALL
SELECT
n.id, t.ancestors || n.is
subofid, t.depth + 1,
n.issubofid = ANY(t.ancestors)
FROM projets
projet n, tree t
WHERE n.issubofid = t.id
AND NOT t.cycle
)
SELECT n.num
stringprojet, n.description, n.id, n.issubofid, p.classement
FROM projetsprojet n
INNER JOIN tree USING (id)
INNER JOIN projets
typeprojet as p on n.typeprojetid = p.id
WHERE %s = ANY(ancestors) AND n.axeid = %s AND n.annee = %s AND n.issubofid = %s
ORDER BY n.num_projet
""" % (p, a, annee, p)

    with connection.cursor() as cursor:
        cursor.execute(sql_child)
        rows = cursor.fetchall()

        for r in rows:
            g = [(r[0], r[1])]
            recurs = get_child(r[2], a, annee)
            if recurs:
                g = [*g, *recurs]
            if g:
                l.append(g)

    return [*l]

def flatten(sequence):

    def flat(seq):
        if not seq:
            yield None
        else:
            if isinstance(seq, tuple):
                yield seq
            elif isinstance(seq, str):
                yield tuple()
            else:
                yield from flat(seq.pop(0))
                yield from flat(seq)

    def group(h, seq, n, default=()):
        ret = []
        for line in flat(seq):
            if line:
                ret.append(line)
            elif ret:
                while len(ret) < n - 1:
                    ret.append(default)
                yield [h, *ret]
                ret = []

    # https://stackoverflow.com/a/6039138/1117028
    depth = lambda l: isinstance(l, list) and (max(map(depth, l)) + 1) if l else 1

    header, *lines = sequence[0]
    n_fields = depth(lines)

    return group(header, lines, n_fields)

def flat_list(l):
    """
        transforme un arbre (liste de listes...) en une liste à 1 seul niveau
    """
    R = []
    for elem in l:
        if isinstance(elem, list):
            R.extend(flat_list(elem))
        else:
            R.append(elem)
    return R

for axe in Axe.objects.all().order_by('num_axe'):
    liste_projets = []
    for projet in Projet.objects.filter(axe_id=axe.id, is_sub_of__isnull=True).order_by('num_projet'):

        # childs = [(projet.axe.num_axe, projet.axe.description),
        #           (projet.num_string_projet, projet.description)] + get_child(projet.pk, axe.id, 2018)
        childs = get_child(projet.pk, axe.id, 2018)
        for liste in childs:
            if len(childs) > 1:
                liste_projets.append(flat_list(flatten([[*liste]])))

            else:
                liste_projets.extend(flatten(childs))
    print(liste_projets)
0 votes

ben @grandpetit ça vo pas ? :D

Si je ne me trompe @bidochon : n = [[e[0],e[1][0]] for e in l] ;)

répondu il y a 5 jours par pydidi (238 points)

Un grand merci pur cette aide précieuse.

je vais tester ça dès que possible

Un grand merci pour cette aide précieuse.

je vais tester ça dès que possible

zut, ça marche pas.
on vas continuer de chercher.

merci quand même

...