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 Delphi Discussion :

Y-a-t-il plus rapide pour enlever les accents ?


Sujet :

Langage Delphi

  1. #41
    Membre chevronné
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    721
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2006
    Messages : 721
    Points : 1 876
    Points
    1 876
    Par défaut
    Citation Envoyé par Rubicon Voir le message
    Y aurait-il plus rapide ?
    Pour déterrer un sujet vieux de 15 ans ?

  2. #42
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 683
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 683
    Points : 13 092
    Points
    13 092
    Par défaut
    Citation Envoyé par Rubicon Voir le message
    Je pleure en voyant les différentes réponses et tentatives.
    Jolie entrée en matière. Salut à toi aussi !

    Citation Envoyé par Rubicon Voir le message
    Et avec les caractères UNICODES, il suffit de créer un tableau de 65536 caractères type TUnicodeChar
    Pas d'unicode en 2007 sous Delphi je te rappelle.

    Mais je pleure aussi en voyant ta liste ; jamais entendu parler de FoldString ? Cette API est pourtant disponible depuis Windows 2000... Voici un exemple qui date de 2009 !

    Papy214 avait aussi proposé une jolie variante à base de TEncoding en 2017.

    Et non, il ne suffit pas de créer un tableau (à moins de d'abord normaliser les chaînes à coup de NormalizeString) puisque Ä, pour un même affichage, peut se coder #$C4 ou décomposé #$41#$308 (A + ¨).

  3. #43
    Candidat au Club
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2023
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2023
    Messages : 3
    Points : 3
    Points
    3
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Jolie entrée en matière. Salut à toi aussi !


    Pas d'unicode en 2007 sous Delphi je te rappelle.
    Si: TNTUnicode

    Mais je pleure aussi en voyant ta liste ; jamais entendu parler de FoldString ? Cette API est pourtant disponible depuis Windows 2000... Voici un exemple qui date de 2009 !
    Trop d'exceptions, trop lent.

    Le tableau ne fait les minuscules, majuscules, diacritiques, sait de quelle langue est un caractère (sympa pour séparer les séquence en en langue Hiragana/Katagana/Occidental etc.. quand il n'y a aucun espace entre eux), et on sait quel type de caractère, ce qui permet de nombreuses combinaisons.

    Papy214 avait aussi proposé une jolie variante à base de TEncoding en 2017.
    Oui, trop lent. SCASW est plus rapide que CASE... et sans tableau !

    Et non, il ne suffit pas de créer un tableau (à moins de d'abord normaliser les chaînes à coup de NormalizeString) puisque Ä, pour un même affichage, peut se coder #$C4 ou décomposé #$41#$308 (A + ¨).
    Ce sont des combinaisons spécifique rares qui peuvent se faire avant.

  4. #44
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 447
    Points : 24 849
    Points
    24 849
    Par défaut
    Il est évident que reprendre un code basé sur Char de 2007 donc AnsiChar ne peut absolument pas être recopié dans un Delphi récent Unicode où Char est un WideChar
    Idem pour la manipulation de chaine, en 2007 Length et Size étaient confondues ce qui est faux en Unicode

    Sans parler de tenter de prendre de l'ASM 32Bits et le passer en ASM 64Bits

    Comme ce type déclaré

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TUnicodesChars = array[0..$FFFF] of TUnicodeChar;
    Autant être le plus proche de la réalité
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TUnicodesChars = array[WideChar] of TUnicodeChar;
    ce qui simplifie la fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    function Minuscule(WCh: WideChar): WideChar;
    begin
      Result := UnicodesChars[WCh].LowCase;
    end;


    Mais comme le fait remarquer AndNotOr, FoldString ou TEncoding, ça sera mieux que des fonctions approximatives bricolés dans son coin face à des fonctions OS éprouvés par des milliards d'utilisateurs.


    EDIT :
    J'ai retrouvé un code de 2004 pour D3, très similaire au proposition avec du array[Char]
    Mais comme c'était pour une recherche médicale, j'avais poussé le vice à gérer ¾½¼ pour que l'utilisateur puisse trouver son article avec '1/2' en toutes lettres, évidemment les ligatures étaient aussi gérées, pour cœur et œdème pour citer les plus facile à trouver pour un informaticien comme exemple

    FoldString aurait remplacé une unité de 1000 lignes.
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #45
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 683
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 683
    Points : 13 092
    Points
    13 092
    Par défaut
    Citation Envoyé par Rubicon Voir le message
    Trop d'exceptions
    Ah bon Par exemple ?

    Citation Envoyé par Rubicon Voir le message
    Le tableau ne fait les minuscules, majuscules, diacritiques, sait de quelle langue est un caractère (sympa pour séparer les séquence en en langue Hiragana/Katagana/Occidental etc.. quand il n'y a aucun espace entre eux), et on sait quel type de caractère, ce qui permet de nombreuses combinaisons.
    Quel rapport avec la suppression des accents ?

    Citation Envoyé par Rubicon Voir le message
    Oui, trop lent. SCASW est plus rapide que CASE... et sans tableau !
    Pas vu de CASE et une chaîne n'est-ce pas un tableau de caractères ?

    Ta routine à base de SCASW (et une liste incomplète) est certainement rapide pour traiter un caractère mais pour une chaîne ce sera un CALL par char ; ce sera juste le principe le plus lent de tous (inline n'est pas possible dû à l'assembleur). Un essai à partir de ce texte, (répété 10 000x sinon c'est pas mesurable) montre les résultats suivants : TEncoding = 109ms, FoldString = 1.393s et SCASW = 3.698s.

    Sans surprise ta fonction a été intégrée ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    function TexteSansAccent(const aValue: string): string;
    begin
      SetLength(Result, aValue.Length);
     
      for var i := 1 to aValue.Length do
        Result[i] := SansAccent(aValue[i]);
    end;

    Et avec ton tableau unicode, comment vas-tu savoir que tu es dans une zone valide sans CASE, comment traites-tu les surrogates et d'ailleurs pourquoi 65 536 puisque l'unicode peut contenir 1 114 111 entrées ?

    Citation Envoyé par Rubicon Voir le message
    Ce sont des combinaisons spécifique rares qui peuvent se faire avant.
    Et donc tu vas perdre du temps à normaliser les chaînes... au cas où !

  6. #46
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 447
    Points : 24 849
    Points
    24 849
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    d'ailleurs pourquoi 65 536 puisque l'unicode peut contenir 1 114 111 entrées ?
    C'est vrai que l'on y pense peu que c'est de UTF-16 qui à l'instar de l'UTF-8 a aussi des tableaux d'extension pour un second élément de 16 bits

    Déjà que le tableau TUnicodesChars pour 65 536 ça doit occuper 524Ko à plus de 4Mo pour l'ensemble des combinaisons actuelles (rien ne dit que d'autres extension ne peuvent pas être ajoutées)
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  7. #47
    Candidat au Club
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2023
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2023
    Messages : 3
    Points : 3
    Points
    3
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Ah bon Par exemple ?
    Faut juste aller voir sur le site cité : https://learn.microsoft.com/en-us/wi...et-foldstringw

    Quel rapport avec la suppression des accents ?
    SCASW est en réponse à la première question sur l'algo de conversion accent/sans accent proposé, que j'ai décliné.

    Pas vu de CASE et une chaîne n'est-ce pas un tableau de caractères ?
    Le tableau de caractère n'a rien a voir avec SCASW.

    Ta routine à base de SCASW (et une liste incomplète) est certainement rapide pour traiter un caractère mais pour une chaîne ce sera un CALL par char ; ce sera juste le principe le plus lent de tous (inline n'est pas possible dû à l'assembleur). Un essai à partir de ce texte, (répété 10 000x sinon c'est pas mesurable) montre les résultats suivants : TEncoding = 109ms, FoldString = 1.393s et SCASW = 3.698s.

    Sans surprise ta fonction a été intégrée ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    function TexteSansAccent(const aValue: string): string;
    begin
      SetLength(Result, aValue.Length);
     
      for var i := 1 to aValue.Length do
        Result[i] := SansAccent(aValue[i]);
    end;
    On peut voir les 2 autres algo (TEncoding et FoldString ) ?

    Et avec ton tableau unicode, comment vas-tu savoir que tu es dans une zone valide sans CASE, comment traites-tu les surrogates et d'ailleurs pourquoi 65 536 puisque l'unicode peut contenir 1 114 111 entrées ?
    Oui, le nombre augmente chaque année. Il a été décidé de limiter les "caractères" unicodes à un tableau de 16 bits pour plus de rapidité.
    Chaque caractère, ou symbole de syllabe, a sa propre langue. On découpe les termes dans la langue souhaitée. De nombreux traducteurs dans le monde (en ligne) utilisent cette méthode depuis 2003.

  8. #48
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 683
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 683
    Points : 13 092
    Points
    13 092
    Par défaut
    Citation Envoyé par Rubicon Voir le message
    Faut juste aller voir sur le site cité : https://learn.microsoft.com/en-us/wi...et-foldstringw
    Ben je vois pas grand chose à part les habituels problèmes d'allocation ou de validité.

    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
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    function NoAccent(const Source: string): string;
    var
     K: TArray<Byte>;
    begin
      K := TEncoding.Convert(TEncoding.Unicode, TEncoding.ASCII, TEncoding.Unicode.GetBytes(Source));
      Result := StringOf(K);
    end;
     
    function RemoveDiacritics(const aValue: string): string;
    begin
      SetLength(Result, FoldString(MAP_COMPOSITE, PChar(aValue), Length(aValue), nil, 0));
      FoldString(MAP_COMPOSITE, PChar(aValue), Length(aValue), PChar(Result), Length(Result));
     
      for var i := Result.Length downto 1 do
        if Result[i].GetUnicodeCategory = TUnicodeCategory.ucNonSpacingMark then
          Delete(Result, i, 1);
    end;
     
    function SansAccent(WCh : WideChar): WideChar;
    const
      Char_Accents      : PWideChar = 'ÀÁÂÃÄÅàáâãäåÒÓÔÕÖØòóôõöøÈÉÊËèéêëÇçÌÍÎÏìíîïÙÚÛÜùúûüÿÑñ';
      Char_Sans_Accents : PWideChar = 'AAAAAAaaaaaaOOOOOOooooooEEEEeeeeCcIIIIiiiiUUUUuuuuyNn';
    asm
           OR      AX, AX
           JE      @@2
           MOV     ECX, 53
           PUSH    EDI
           MOV     EDI, Char_Accents
           REPNE   SCASW      // Recherche le caractère
           JNE     @@1        // Pas trouvé
           SUB     EDI, Char_Accents
           ADD     EDI, Char_Sans_Accents
           MOV     AX, [EDI - 2]
    @@1:   POP     EDI
    @@2:
    end;
     
    function TexteSansAccent(const aValue: string): string;
    begin
      SetLength(Result, aValue.Length);
     
      for var i := 1 to aValue.Length do
        Result[i] := SansAccent(aValue[i]);
    end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      const Text = TStringList.Create;
     
      Text.LoadFromFile('D:\Temp\nouveau 1.txt', TEncoding.UTF8);
     
      var Watch := TStopWatch.StartNew;
      for var i := 1 to 10000 do NoAccent(Text.Text);
      Memo1.Lines.Add(Watch.ElapsedMilliseconds.ToString);
     
      Watch := TStopWatch.StartNew;
      for var i := 1 to 10000 do RemoveDiacritics(Text.Text);
      Memo1.Lines.Add(Watch.ElapsedMilliseconds.ToString);
     
      Watch := TStopWatch.StartNew;
      for var i := 1 to 10000 do TexteSansAccent(Text.Text);
      Memo1.Lines.Add(Watch.ElapsedMilliseconds.ToString);
    end;

  9. #49
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 683
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 683
    Points : 13 092
    Points
    13 092
    Par défaut
    Citation Envoyé par Rubicon Voir le message
    Y aurait-il plus rapide ?
    Tiens une petite modif qui multipliera la vitesse par 10. Inutile en effet de tester les caractères ASCII puisqu'ils sont déjà sans accent.

    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
    function SansAccent(WCh : WideChar): WideChar;
    const
      Char_Accents      : PWideChar = 'ÀÁÂÃÄÅàáâãäåÒÓÔÕÖØòóôõöøÈÉÊËèéêëÇçÌÍÎÏìíîïÙÚÛÜùúûüÿÑñ';
      Char_Sans_Accents : PWideChar = 'AAAAAAaaaaaaOOOOOOooooooEEEEeeeeCcIIIIiiiiUUUUuuuuyNn';
    asm
    //       OR      AX, AX
    //       JE      @@2
           CMP     AX, 128
           JB      @@2
     
           MOV     ECX, 53
           PUSH    EDI
           MOV     EDI, Char_Accents
           REPNE   SCASW      // Recherche le caractère
           JNE     @@1        // Pas trouvé
           SUB     EDI, Char_Accents
           ADD     EDI, Char_Sans_Accents
           MOV     AX, [EDI - 2]
    @@1:   POP     EDI
    @@2:
    end;

+ Répondre à la discussion
Cette discussion est résolue.
Page 3 sur 3 PremièrePremière 123

Discussions similaires

  1. Y-a-t-il plus rapide pour enlever les mots vides ?
    Par Bruno13 dans le forum Delphi
    Réponses: 33
    Dernier message: 26/07/2007, 17h03
  2. [XHTML] Moyen plus rapide pour mettre mes pages en XHTML
    Par Linoa dans le forum Balisage (X)HTML et validation W3C
    Réponses: 6
    Dernier message: 30/08/2005, 17h46
  3. Algo le plus rapide pour trouver une répétition ?
    Par AsmCode dans le forum Algorithmes et structures de données
    Réponses: 3
    Dernier message: 28/07/2005, 00h26
  4. Réponses: 16
    Dernier message: 19/05/2005, 16h20
  5. [FoxPro]Instruction pour enlever les accents ?
    Par Fab-FoxPro dans le forum Autres SGBD
    Réponses: 2
    Dernier message: 19/08/2003, 15h46

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