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 :

Question sur la fonction SORT + UTF-8


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Août 2010
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 6
    Par défaut Question sur la fonction SORT + UTF-8
    Bonjour,

    J'ai consulté rapidement les indications sur Sort (j'ai également lu la page des mongeurs), mais je n'ai pas trouvé d'information.

    J'aimerais savoir si la fonction sort peut accepter l'UTF-8 et non plus se baser sur l'encodage ASCII.
    Je veux trier du xml selon des termes qui peuvent commencer par un caractère accentué, par exemple un terme comme "âge".

    J'ai deux ressources, l'une classe "âge" dans les A, et l'autre l'indique après les Z. L'objectif est que l'ordre soit le même pour les deux fichiers.

    Merci pour votre aide !

  2. #2
    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
    Sauf erreur, pour que la fonction sort (et toutes les comparaisons alphabétiques) fonctionnent selon la langue, il convient d'utiliser la locale.
    Si les variables d'environnement ne positionnent pas la locale par défaut à la bonne valeur (fr_FR), il faut alors la forcer dans le script:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    use locale; # si les variables d'environnement sont correctement positionnées, cela devrait suffire
    use POSIX qw(setlocale); # pour forcer une locale donnée
    setlocale("fr_FR"); # pour forcer la locale fr_FR
    Pour plus d'infos : perldoc perllocale, perldoc locale

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Août 2010
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 6
    Par défaut
    En effet Philou67430, en ajoutant ce que tu proposes j'obtiens déjà un premier résultat intéressant.

    Maintenant je me questionne. Voici un petit programme de test que j'ai fait à partir de tes indications :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #!/usr/bin/perl
     
    use utf8;
    use locale; # si les variables d'environnement sont correctement positionnées, cela devrait suffire
    use POSIX qw(setlocale); # pour forcer une locale donnée
    setlocale("fr_FR"); # pour forcer la locale fr_FR
     
    @lines = (abaca, balou, âge, zephiroth, zéphiroth);
    my @dico = sort @lines;
    print @dico;
    J'obtiens ce résultat (en rajoutant des espaces bien sûr):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    âge abaca balou zéphiroth zephiroth
    Même si ce classement est étrange, il peut convenir pour ce que je souhaite faire. Mais histoire de pousser un peu plus loin, je me demandais si c'était normal d'avoir par exemple ÂGE avant ABACA. Je me dis qu'en UTF8 le â doit arriver avant quelque chose comme ça.

    Donc en fait les deux questions sont :
    1) est-ce normal ?
    2) peut-on changer cet état ?

    En sachant que c'est uniquement par curiosité (et parce que j'essaie d'être jusqu'au-boutiste), ce que j'obtiens me satisfait déjà.

    En tout cas merci pour l'information Philou !

  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
    Je ne sais pas si c'est normal ou nom, car je ne connais pas la règle qui défini l'ordre alphabétique pour les jeux de caractères contenant des diacritiques (des accentuations pour faire simple).

    Du coup, dans les recommandations que je t'ai données, l'ordre alphabétique identifié a comme une lettre différente de â et de à, et de fait, les place à un ordre différent. Ce qui explique que abaca soit après âge (ou avant peut importe).

    Si ton désir est de considéré que â et a doivent avoir le même ordre alphabétique, il faut alors supprimer la diacriticité dans le tri.

    Pour ce faire, il existe un module (même deux) pour cela. De même, pour éviter un traitement lourd dans l'algorithme de tri, je vais utiliser une technique de pipeline (la transformée Schwartzienne) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #!/usr/bin/perl
     
    use utf8;
    use locale; # si les variables d'environnement sont correctement positionnées, cela devrait suffire
    use POSIX qw(setlocale); # pour forcer une locale donnée
    setlocale("fr_FR"); # pour forcer la locale fr_FR
    use Text::StripAccents;
     
    @lines = (abaca, balou, âge, zephiroth, zéphiroth);
    my @dico =
      map  { $_->[0] }
      sort { $a->[1] cmp $b->[1] }
      map  { [ $_ => stripaccents($_) ] } @lines;
    print join ", ", @dico;

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Août 2010
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 6
    Par défaut
    Oui, tu as bien cerné mon problème, et merci pour la solution, elle fonctionne sans problème.

    Je pense avoir fait le tour de la question, il me reste une dernière chose à demander. Apparemment 'sort' est déconseillé pour de gros fichiers, ce qui pourrait être mon cas (tout dépend de ce qu'on entend par "gros". Pour ma part ça concerne plusieurs milliers d'items, je suppose que c'est "gros").

    Que faut-il utiliser alors ? Un module du type File::Sort ?

  6. #6
    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
    Un algoritme de tri a toujours ses limites, liées à ses performances.
    Sort implique en plus que l'ensemble des données soient présentent en mémoire.

    Cela dit, le mieux est de l'essayer avant de l'adopter. A priori, jusqu'à plusieurs centaines de milliers d'items, je pense qu'il n'y a pas de problème majeur.

    Exemple, en reprenant le script précédent, mon PC (Core 2 duo déjà bien chargé en mémoire et en CPU) n'a mis que 27s pour lire, trier et afficher les plus de 80000 mots de la bible.
    Le script :
    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
    #!/usr/bin/perl
     
    use utf8;
    use locale; # si les variables d'environnement sont correctement positionnées, cela devrait suffire
    use POSIX qw(setlocale); # pour forcer une locale donnée
    setlocale("fr_FR"); # pour forcer la locale fr_FR
    use Text::StripAccents;
     
    my @lines;
    open my $BIBLE, "<", $ARGV[0] or @lines = qw(abaca balou âge zephiroth zéphiroth);
    @lines = map { split /\W+/ } <$BIBLE> if !@lines;
    my @dico =
      map  { $_->[0] }
      sort { $a->[1] cmp $b->[1] }
      map  { [ $_ => stripaccents($_) ] } @lines;
    print join ", ", @dico;
    Le résultat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    time perl sort_accent.pl bible.txt
    ...
    real    0m27.821s
    user    0m27.264s
    sys     0m0.140s
    Le temps est de 1mn 11 pour les 137000 mots du dictionnaire français (/usr/share/dict/french sous Ubuntu).

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

Discussions similaires

  1. [Dates] Question sur les fonctions Date
    Par cerede2000 dans le forum Langage
    Réponses: 2
    Dernier message: 28/10/2006, 17h26
  2. Question sur la fonction recv
    Par Mr_Chut dans le forum Réseau
    Réponses: 14
    Dernier message: 15/09/2006, 12h43
  3. Question sur les fonctions "send()" et "recv(
    Par damien99 dans le forum MFC
    Réponses: 6
    Dernier message: 10/02/2006, 20h47
  4. Réponses: 1
    Dernier message: 08/02/2006, 11h18
  5. Réponses: 2
    Dernier message: 21/12/2005, 09h39

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