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

Langage Perl Discussion :

Changer la numérotation d'un sommaire


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 822
    Par défaut Changer la numérotation d'un sommaire
    Bonsoir,

    Cette fois, je pose une question car j'ai un petit problème à résoudre.
    Je dois refaire la numérotation de sommaires (contenu dans des fichiers XML) en fonction de certains critères.

    Les XML importent peu, je vais vous montrer un exemple.

    Je vais vous représenter un sommaire sous forme de hash (issu d'un parsing), on verra si c'est la bonne solution car on perd l'ordre.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    my %sommaire = (
    	'1*' => { '1-a',  '1-b', },
    	'2'  => { '2-a*', '2-b' => { '2-b-A', '2-b-B' '2-b-C' }, },
    	'3*' => { '3-a',  '3-b', },
    	'4'  => { '4-a',  '4-b', },
    );
    En gros, on a quatre chapitres numérotés de 1 à 4 (ça aurait pu être de A à D).
    Le chapitre 1 a deux sous-chapitres 1-a et 1-b et ainsi de suite.

    Vous constatez dans certains cas que nous avons des étoiles (*).
    Cela signifie que dans notre nouveau sommaire, ces chapitres (et sous chapitres) ne devront plus compter dans la numérotation. On rajoutera un préfixe 0- afin de les isoler de façon unique. Il faut donc reclaculer le sommaire.
    Notre sommaire devrait devenir le suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    my %sommaire_final = (
    	'0-1*' => { '0-1-a',  '0-1-b', },
    	'1'    => { '0-1-a*', '1-a' => { '1-a-A', '1-a-B' '1-a-C' }, },
    	'0-3*' => { '0-3-a',  '0-3-b', },
    	'2'    => { '2-a',    '2-b', },
    );
    En constate que le chapitre 4 et devenu chapitre 2, que le chapitre 2-b-A est devenu 1-a-A...
    Les autres avec étoiles ont été renommés.

    Ma problématique est donc de trouver une solution à ce problème quelque soit le placement des étoiles.
    De plus, je dois être capable de faire la correspondance entre chaque ancien et nouveau chapitre afin d'effectuer les changement.
    • 2-b-A devient 1-a-A ;
    • 2 devient 1 ;
    • 4 devient 2 ;
    • ...


    N.B. La numérotation d'un sommaire peut-être 1, i, I, a ou A. Et on peut avoir plusieurs niveaux sans limite. Dans l'exemple ci-dessus, il y a trois niveaux.

    Toute aide est la bienvenue !


  2. #2
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Billets dans le blog
    1
    Par défaut
    Hum, j'ai peut-être une petite idée, mais je ne suis pas sûr de bien comprendre.

    Ton sommaire de base:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    my %sommaire = (
    	'1*' => { '1-a',  '1-b', },
    	'2'  => { '2-a*', '2-b' => { '2-b-A', '2-b-B' '2-b-C' }, },
    	'3*' => { '3-a',  '3-b', },
    	'4'  => { '4-a',  '4-b', },
    );
    Je comprends que tu veux supprimer le chapitre 1. Mais pas bien ce que doivent devenir les sous-chapitres 1-a et 1-b (je suppose qu'ils doivent subsister, mais sous quelle numérotation?). De même, si 1 disparaît, 2 est-il renommé?

  3. #3
    Membre chevronné Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Par défaut
    Bonjour djibril,

    tes hashes ont l'air plutôt malades

    Quoi qu'il en soit on n'en a pas besoin car il y a une hiérarchie implicite qui suffit à structurer le problème.

    Ci-dessous une version limitée (0-9, a-z, A-Z, pas de chiffres romains) pour illustrer le principe général.
    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
    # sommaire1.pl
    use strict;
    use warnings;
    use 5.010;
     
    my @sections = qw(2-b-B 2-b-C 3* 3-a 3-b 4 4-a 4-b 1* 1-a 1-b 2 2-a* 2-b 2-b-A);
     
    my (@d, %k, %p) = map { ord($_) - 1 } qw(1 a A);
    say +(q{  } x split q{-}), qq{$_ (ex $p{$_})} for map {
        ++$d[my $n = -1 + split q{-}];
        $p{my $x = join q{-}, map chr, @d[0 .. $n]} = $_;
        $x;
    } grep { 
        my ($b, $p, $m) = m/^((?:(.*)-)?.*?)([*])?$/;
        !$m and (!$p or $k{$p}) and ++$k{$b} and $b
    } sort @sections;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Taisha:~/tttmp/sommaire $ perl sommaire1.pl
      1 (ex 2)
        1-a (ex 2-b)
          1-a-A (ex 2-b-A)
          1-a-B (ex 2-b-B)
          1-a-C (ex 2-b-C)
      2 (ex 4)
        2-b (ex 4-a)
        2-c (ex 4-b)
    Taisha:~/tttmp/sommaire $
    Le sort est essentiel. Le grep fait la sélection, le map le renommage.

  4. #4
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Bas Rhin (Alsace)

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

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Par défaut
    J'adore ce genre de petit défit

    Je suis parti sur un algorithme qui ne suppose rien sur la manière dont la numérotation à chaque niveau s'incrémente, dès lors que l'on peut considérer que dans le nouveau sommaire, tous les numéros de chaque niveau sont des numéros qui existent déjà dans le sommaire actuel, et qu'il suffit "de les décaler", "de les préfixer" ou "d'en modifier le préfixe avec des valeurs connues".

    Voici le programme, qui semble faire ce que Djibril souhaite :

    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    #!/usr/bin/perl
     
    use strict;
    use warnings;
    use feature qw(:5.14);
     
    use Data::Dumper;
    $Data::Dumper::Sortkeys++;
     
    my $sommaire = {
    	'1*' => { '1-a' => undef,  '1-b' => undef, },
    	'2'  => { '2-a*' => undef, '2-b' => { '2-b-A' => undef, '2-b-B' => undef, '2-b-C' => undef }, },
    	'3*' => { '3-a' => undef,  '3-b' => undef, },
    	'4'  => { '4-a' => undef,  '4-b' => undef, },
    };
     
    say Data::Dumper->Dump([$sommaire], [qw($sommaire)]);
     
    sub update_level($;@);
    sub update_level($;@) {
      my ($s, @changes) = @_;
     
      my $new_s = { };
      return undef if !defined $s;
     
      my @level;
      foreach my $num (sort keys %$s) {
        my $sub_level = $s->{$num};
        foreach my $change (@changes) {
          my ($old, $new) = @$change;
          $num =~ s/^$old/$new/;
        }
        my $to_remove = $num =~ s/\*$//;
        push @level, $num;
        if ($to_remove) {
          $new_s->{"0-$num"} = update_level($sub_level, @changes, [ $num, "0-$num" ]);
        }
        else {
          my $current_num = shift @level;
          $new_s->{$current_num} = update_level($sub_level, @changes, [ $num, $current_num ]);
        }
      }
     
      return $new_s;
    }
     
    my $new_sommaire = update_level($sommaire);
     
    say Data::Dumper->Dump([$new_sommaire], [qw(*new_sommaire)]);

  5. #5
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 822
    Par défaut
    Citation Envoyé par Philou67430 Voir le message
    J'adore ce genre de petit défit

    Je suis parti sur un algorithme qui ne suppose rien sur la manière dont la numérotation à chaque niveau s'incrémente, dès lors que l'on peut considérer que dans le nouveau sommaire, tous les numéros de chaque niveau sont des numéros qui existent déjà dans le sommaire actuel, et qu'il suffit "de les décaler", "de les préfixer" ou "d'en modifier le préfixe avec des valeurs connues".

    Voici le programme, qui semble faire ce que Djibril souhaite :

    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    #!/usr/bin/perl
     
    use strict;
    use warnings;
    use feature qw(:5.14);
     
    use Data::Dumper;
    $Data::Dumper::Sortkeys++;
     
    my $sommaire = {
    	'1*' => { '1-a' => undef,  '1-b' => undef, },
    	'2'  => { '2-a*' => undef, '2-b' => { '2-b-A' => undef, '2-b-B' => undef, '2-b-C' => undef }, },
    	'3*' => { '3-a' => undef,  '3-b' => undef, },
    	'4'  => { '4-a' => undef,  '4-b' => undef, },
    };
     
    say Data::Dumper->Dump([$sommaire], [qw($sommaire)]);
     
    sub update_level($;@);
    sub update_level($;@) {
      my ($s, @changes) = @_;
     
      my $new_s = { };
      return undef if !defined $s;
     
      my @level;
      foreach my $num (sort keys %$s) {
        my $sub_level = $s->{$num};
        foreach my $change (@changes) {
          my ($old, $new) = @$change;
          $num =~ s/^$old/$new/;
        }
        my $to_remove = $num =~ s/\*$//;
        push @level, $num;
        if ($to_remove) {
          $new_s->{"0-$num"} = update_level($sub_level, @changes, [ $num, "0-$num" ]);
        }
        else {
          my $current_num = shift @level;
          $new_s->{$current_num} = update_level($sub_level, @changes, [ $num, $current_num ]);
        }
      }
     
      return $new_s;
    }
     
    my $new_sommaire = update_level($sommaire);
     
    say Data::Dumper->Dump([$new_sommaire], [qw(*new_sommaire)]);
    @philou, j'ai testé ton programme et il y a un petit souci.
    Le nouvelle hash est parfait. LE seul bémol, est que je suis incapable de faire la liaison entre les anciennes et nouvelles numérotations. Je m'explique.
    • 1* est devenu 0-1
    • 2 est devenu 1
    • 2-b-B est devenu 1-a-B
    • 3* est devenu 2
    • 4 est devenu 2
    • ...

    Comment je fais les correspondances ?

  6. #6
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 822
    Par défaut
    Citation Envoyé par cmcmc Voir le message
    Bonjour djibril,

    tes hashes ont l'air plutôt malades

    Quoi qu'il en soit on n'en a pas besoin car il y a une hiérarchie implicite qui suffit à structurer le problème.

    Ci-dessous une version limitée (0-9, a-z, A-Z, pas de chiffres romains) pour illustrer le principe général.
    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
    # sommaire1.pl
    use strict;
    use warnings;
    use 5.010;
     
    my @sections = qw(2-b-B 2-b-C 3* 3-a 3-b 4 4-a 4-b 1* 1-a 1-b 2 2-a* 2-b 2-b-A);
     
    my (@d, %k, %p) = map { ord($_) - 1 } qw(1 a A);
    say +(q{  } x split q{-}), qq{$_ (ex $p{$_})} for map {
        ++$d[my $n = -1 + split q{-}];
        $p{my $x = join q{-}, map chr, @d[0 .. $n]} = $_;
        $x;
    } grep { 
        my ($b, $p, $m) = m/^((?:(.*)-)?.*?)([*])?$/;
        !$m and (!$p or $k{$p}) and ++$k{$b} and $b
    } sort @sections;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Taisha:~/tttmp/sommaire $ perl sommaire1.pl
      1 (ex 2)
        1-a (ex 2-b)
          1-a-A (ex 2-b-A)
          1-a-B (ex 2-b-B)
          1-a-C (ex 2-b-C)
      2 (ex 4)
        2-b (ex 4-a)
        2-c (ex 4-b)
    Taisha:~/tttmp/sommaire $
    Le sort est essentiel. Le grep fait la sélection, le map le renommage.
    En quoi mon sommaire est malade ?
    Les chapitres de niveau 1 sont des chiffres ou nombres.
    Les chapitres de niveau 2 des lettres en minuscule (d'où 1-a, 1-b...)
    Les chapitres de niveau 3 des lettres majuscule (d'où 2-b-A, 2-b-B...)

    Tout est logique !

  7. #7
    Membre chevronné Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Par défaut
    Citation Envoyé par djibril Voir le message
    En quoi mon sommaire est malade ?
    Les chapitres de niveau 1 sont des chiffres ou nombres.
    Les chapitres de niveau 2 des lettres en minuscule (d'où 1-a, 1-b...)
    Les chapitres de niveau 3 des lettres majuscule (d'où 2-b-A, 2-b-B...)

    Tout est logique !
    C'est peut-être logique mais ce n'est pas un hash Perl bien formé. Il manque une virgule entre '2-b-B' et '2-b-C', mais même avec ça ...

    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
    22
    23
    24
    25
    26
    Taisha:~/tttmp/sommaire $ cat aie.pl 
    my %sommaire = (
    	'1*' => { '1-a',  '1-b', },
    	'2'  => { '2-a*', '2-b' => { '2-b-A', '2-b-B', '2-b-C' }, },
    	'3*' => { '3-a',  '3-b', },
    	'4'  => { '4-a',  '4-b', },
    );
    use Data::Dumper;
    print Dumper(\%sommaire);
    Taisha:~/tttmp/sommaire $ perl aie.pl 
    $VAR1 = {
              '2' => {
                       '2-a*' => '2-b',
                       'HASH(0x96d4dc)' => undef
                     },
              '1*' => {
                        '1-a' => '1-b'
                      },
              '3*' => {
                        '3-a' => '3-b'
                      },
              '4' => {
                       '4-a' => '4-b'
                     }
            };
    Taisha:~/tttmp/sommaire $
    Ce serait mieux de démarrer avec une structure de donnée saine, non ?

    Ou bien de la jeter carrément car comme je l'ai montré on n'en a pas besoin, la liste des numéros de chapitres/sections etc. suffit.

  8. #8
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 822
    Par défaut
    Ah ok, je vois !
    Faut reprendre la structure de philou, ou bien partir d'autre chose si tu veux. C'était surtout pour expliquer la hiérarchie du sommaire.

    Pour mon programme je remplirais ce hash ou tableau comme ça vous arrange.

  9. #9
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 822
    Par défaut
    Citation Envoyé par Lolo78 Voir le message
    Hum, j'ai peut-être une petite idée, mais je ne suis pas sûr de bien comprendre.

    Ton sommaire de base:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    my %sommaire = (
    	'1*' => { '1-a',  '1-b', },
    	'2'  => { '2-a*', '2-b' => { '2-b-A', '2-b-B' '2-b-C' }, },
    	'3*' => { '3-a',  '3-b', },
    	'4'  => { '4-a',  '4-b', },
    );
    Je comprends que tu veux supprimer le chapitre 1. Mais pas bien ce que doivent devenir les sous-chapitres 1-a et 1-b (je suppose qu'ils doivent subsister, mais sous quelle numérotation?). De même, si 1 disparaît, 2 est-il renommé?
    En fait, je ne souhaite pas supprimer le chapitre 1 et 4, mais les cacher. Donc à mon sens, cacher veut dire les exclure de ma numérotation et ceux en rajoutant un préfix (car chaque numérotation doit être unique).
    Un chapitre étoilé veut dire toute sa descendance étoilée.

    Ensuite, je dois recalculer les autres chapitres et sous-chapitres.

    Au final, je pourrais renommer tout mon sommaire avec mon résultat final.

  10. #10
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 822
    Par défaut
    Euh, en entrée, pour moi le plus simple serait de te donner une liste de ce type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    my @sections = qw(i* i-a i-b ii ii-a* ii-b ii-b-A ii-b-B ii-b-C iii* iii-a iii-b iv iv-a iv-b );
    Et en sortie, un hash comme la version de ton prog que j'ai modifiée.

Discussions similaires

  1. [Débutant] Changer la numérotation sc. de l'axe x dans un plot
    Par nels81 dans le forum MATLAB
    Réponses: 2
    Dernier message: 13/04/2013, 15h35
  2. Changer les numérotations des \subsubsection{} par une lettre
    Par amad206 dans le forum Mise en forme
    Réponses: 2
    Dernier message: 09/11/2009, 17h40
  3. changer la numérotation des sections
    Par Infotic dans le forum Mise en forme
    Réponses: 2
    Dernier message: 16/07/2009, 13h27
  4. Changer la numérotation chapitre et sections
    Par timesmoney dans le forum Mise en forme
    Réponses: 5
    Dernier message: 12/05/2008, 23h00
  5. Changer la numérotation des sections
    Par Doniphon dans le forum Mise en forme
    Réponses: 5
    Dernier message: 09/11/2006, 12h35

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