IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Parcourir une liste en yoyo ? [Python 3.X]


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Invité
    Invité(e)
    Par défaut Parcourir une liste en yoyo ?
    Bonjour (et bonne année) ça fait quelques temps que je n'étais pas venu poser une question à la con...

    Exemple : J'ai un texte = "toto va a la plage" et une liste = ["1","2","3","4","5"] comment obtenir ça : "1t2o3t4o 5v4a 3a 2l1a 2p3l4a5g4e". (Vous voyez l'histoire du yoyo ?)
    J'ai bidouiller un truc qui fait le boulot mais c'est pas beau et surement pas très efficace.

    Passez votre chemin si vous avez d'autres choses plus intéressantes à faire ! Mais je me suis dit que ça prendrait 30 secondes à l'un des pro de ce forum...

    Merci quand même ou désolé pour la perte de temps...

    PS : C'est pour faire de la coloration de texte avec les balises [color=#......]
    Dernière modification par Invité ; 14/01/2021 à 01h49.

  2. #2
    Membre éclairé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Juin 2018
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aube (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2018
    Messages : 29
    Par défaut
    hum, pas réussi en une ligne =P

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    from itertools import cycle, chain
     
    def func(txt, n):
        yoyo = cycle(chain(range(1,n),range(n,1,-1)))
        return ''.join(str(next(yoyo))+x if x != ' ' else x for x in txt)
     
    print(func("toto va a la plage",5))

  3. #3
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Citation Envoyé par LeNarvalo Voir le message
    ...question à la con...
    Je confirme...

    Voilà une solution, pas forcément élégante, mais qui donne le résultat:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    texte = "toto va a la plage"
    liste = ["1","2","3","4","5"]
     
    # obtenir une liste au moins aussi longue que texte
    liste = liste[:-1] + list(reversed(liste))[:-1] # => ['1', '2', '3', '4', '5', '4', '3', '2']
    while len(liste)<len(texte):
        liste += liste
     
    # calcul
    i = 0
    j = 0
    resultat = ""
    while i<len(texte):
        if texte[i]==" ":
            resultat += texte[i] # pas d'ajout pour un espace
        else:
            resultat += liste[j] + texte[i]
            j += 1
        i += 1 # caractère suivant   
     
    print(resultat)
    Ce qui donne bien:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1t2o3t4o 5v4a 3a 2l1a 2p3l4a5g4e
    Ce qui complique le code, c'est que les espaces ne font pas l'objet d'un ajout, sinon, on pourrait faire beaucoup plus simple avec la fonction "zip".

  4. #4
    Invité
    Invité(e)
    Par défaut
    Merci à tous les deux !

    Je vais regarder du côté de itertools ce n'est pas vraiment 12345 que je veux insérer mes [color=#......]LETTRE[/color].

    A bientôt pour le prochain épisode !

  5. #5
    Membre éclairé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Juin 2018
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aube (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2018
    Messages : 29
    Par défaut
    Ah?! Juste remplacer les "range" alors:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    from itertools import cycle
     
    def func(txt, lst):
        yoyo = cycle(lst[:-1]+lst[-1:0:-1])
        return ''.join(next(yoyo)+x if x != ' ' else x for x in txt)
     
    print(func("toto va a la plage",['1','2','3','4','5']))

  6. #6
    Membre chevronné
    Homme Profil pro
    Développeur banc de test
    Inscrit en
    Mai 2014
    Messages
    199
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur banc de test
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Mai 2014
    Messages : 199
    Par défaut
    Bonjour,

    j'avais pensé utiliser cycle aussi mais c'est assez simple à faire en fait.

    Pour réaliser le cyclage :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print(liste + liste[1:-1][::-1])
    >> ['1', '2', '3', '4', '5', '4', '3', '2']

    Il suffit ensuite de faire modulo de l'indice de texte :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print(", ".join((liste + liste[1:-1][::-1])[i % (2 * len(liste) - 2)] for i, c in enumerate(texte)))
    >> 1, 2, 3, 4, 5, 4, 3, 2, 1, 2, 3, 4, 5, 4, 3, 2, 1, 2

    Ensuite on gère le cas des espaces en comptant le nombre d'espaces restants par rapport au nombre total d'espaces dans texte, ce sera la retenu qu'il faudra ajouter à l'indexation de liste :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print("".join(str(texte.count(" ") - texte[i + 1:].count(" ")) + c for i, c in enumerate(texte)))
    >> 0t0o0t0o1 1v1a2 2a3 3l3a4 4p4l4a4g4e

    Plus qu'à combiner tout ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print("".join([(liste + liste[1:-1][::-1])[(i - (texte.count(" ") - texte[i + 1:].count(" "))) % (2 * len(liste) - 2)] + c, " "][c == " "] for i, c in enumerate(texte)))
    >> 1t2o3t4o 5v4a 3a 2l1a 2p3l4a5g4e


    Bon par contre si vous insérez un machin de ce genre dans vos codes pensez à commenter.

  7. #7
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par YCL-1 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print("".join([(liste + liste[1:-1][::-1])[(i - (texte.count(" ") - texte[i + 1:].count(" "))) % (2 * len(liste) - 2)] + c, " "][c == " "] for i, c in enumerate(texte)))
    Bon par contre si vous insérez un machin de ce genre dans vos codes pensez à commenter.
    Nice ! J'aurais jamais pensé à ça (et encore moins réussit).

  8. #8
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 833
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par tyrtamos Voir le message
    Voilà une solution, pas forcément élégante, mais qui donne le résultat:
    Ah, c'est la partie du forum que j'aime: celui où chacun y va de sa petite solution

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def func(txt, n):
    	nb=(tuple(range(1, n+1)) + tuple(range(n-1, 1, -1))) * (len(txt)//n+1)
    	res=""
    	i=0
    	for l in txt:
    		res+="%d%s" % (nb[i], l)
    		if not l.isspace(): i+=1
    	# for
    	return res
    # func()
     
    print(func("toto va a la plage", 5))
    C'est vrai que l'espace à sauter (là j'ai utilisé isspace() et ainsi éliminé tout ce qui était "de type" espace, comme les tabulations) rend difficile de faire ça en une ligne via zip().

    Citation Envoyé par LeNarvalo Voir le message
    Mais je me suis dit que ça prendrait 30 secondes à l'un des pro de ce forum...
    Ca m'a pris quand-même un peu plus de temps (dans les 10mn quoi)...

    Citation Envoyé par YCL-1 Voir le message
    Ensuite on gère le cas des espaces en comptant le nombre d'espaces restants par rapport au nombre total d'espaces dans texte, ce sera la retenu qu'il faudra ajouter à l'indexation de liste
    Ouais je suis allé au plus simple: je génère le "yoyo" comme étant de longueur égale au texte de base, sans me préoccuper des espaces. Il peut être alors plus long que nécessaire mais je considère que c'est peanut (dans ma première version j'avais même écrit *n ce qui générait un yoyo de n cycles).

    Sinon bravo à Daguhh pour sa solution à base d'itertools et chain. Jolie maitrise de ces librairies
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  9. #9
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 062
    Par défaut
    Peut-être un peu moins cryptique, histoire de goût on va dire,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    def func(txt, lst):    
        yoyo = cycle(lst + lst[::-1][1:-1])
        return ''.join(next(yoyo) + x if x != ' ' else x for x in txt)

  10. #10
    Membre éclairé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Juin 2018
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aube (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2018
    Messages : 29
    Par défaut
    histoire de goût on va dire,
    Je sais pas sil 'analogie est parlante, mais je préfère assembler comme ça :
    Que comme ça:
    Et oui, j'imagine qu'inverser et slicer en deux temps est plus parlant. Un compromis? =P
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    lst[:-1] + lst[::-1][:-1]
    rend difficile de faire ça en une ligne via zip().
    en comptant le nombre d'espaces
    pour sa solution à base d'itertools
    Voici pour la solution : on supprime les espaces, on zippe, on remet les espaces. (Et on ajoute du functools!)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    >>> from itertools import cycle, accumulate
    >>> from functools import reduce
    >>> 
    >>> texte = "toto va a la plage"
    >>> liste = ["1","2","3","4","5"]
    >>> 
    >>> lettres = [''.join(x) for x in zip(cycle(liste[:-1]+liste[:0:-1]),texte.replace(' ',''))]
    >>> lettres
    ['1t', '2o', '3t', '4o', '5v', '4a', '3a', '2l', '1a', '2p', '3l', '4a', '5g', '4e']
    >>> 
    >>> indices = list(accumulate([len(x)+1 for x in texte.split(' ')], initial=-1))[1:-1]
    >>> indices
    [4, 7, 9, 12]
    >>> 
    >>> ''.join(reduce(lambda x,y : x[:y] + [' '] + x[y:], indices, lettres))
    '1t2o3t4o 5v4a 3a 2l1a 2p3l4a5g4e'
    >>>
    Soit l'expression en "une ligne":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    from itertools import cycle, accumulate
    from functools import reduce
     
    texte = "toto va a la plage"
    liste = ["1","2","3","4","5"]
     
    ''.join(reduce(lambda x,y : x[:y] + [' '] + x[y:], list(accumulate([len(x)+1 for x in texte.split(' ')], initial=-1))[1:-1], [''.join(x) for x in zip(cycle(liste[:-1]+liste[:0:-1]),texte.replace(' ',''))]))

  11. #11
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Je suis toujours impressionné par les problèmes compliqués qu'on peut résoudre en une seule ligne en Python, et il m'arrive aussi d'y prendre plaisir.

    Il reste que ce n'est pas toujours une bonne solution, au moins pour deux raisons:

    - c'est rapidement illisible, et il faudra faire un gros effort pour se rappeler ce que ça fait dans 6 mois. Et dans une entreprise, les programmeurs qui font ça sont rapidement pris pour des gens dangereux, parce que personne ne peut reprendre leurs codes une fois qu'ils sont partis.

    - les quelques tests que j'ai fait sur le sujet m'ont montré que le code Python très concis n'est pas forcément plus rapide.

    Il reste que c'est très amusant...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Parcourir une liste de fichiers
    Par viny dans le forum Langage
    Réponses: 3
    Dernier message: 10/01/2007, 17h21
  2. Parcourir une liste de checkbox
    Par fet dans le forum ASP
    Réponses: 3
    Dernier message: 25/07/2006, 12h35
  3. Parcourir une liste deroulante
    Par brandon dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 17/02/2005, 19h03
  4. parcourir une liste de la fin vers le début
    Par zdra dans le forum SL & STL
    Réponses: 12
    Dernier message: 06/02/2005, 18h40
  5. [langage] Parcourir une list de array
    Par nledez dans le forum Langage
    Réponses: 4
    Dernier message: 08/11/2004, 17h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo