Tri avec accent

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Bmld76
Messages : 116
Inscription : dim. 09/janv./2022 12:47

Tri avec accent

Message par Bmld76 »

Bonsoir,

En cherchant une solution pour trier une liste en cliquant sur l'entête, je me suis aperçu d'un problème de tri avec des caractères accentués. Le problème est-il connu, y a-t- il une solution ?

je vous met 2 programmes mettant en évidence ce problème de tri, Jérome est toujours après Jules. le premier pour Mac avec sélection d'entête, ma solution est assez simple, et un programme universel avec boutons.

Sélection par entête

Code : Tout sélectionner

EnableExplicit
Global quit,liste = 10 , event, Gadget

Structure Person
  nom.s
  prenom.s
  id.i
EndStructure

Global Dim tabTries.Person(2)
tabTries(0)\nom =  "Lager" : tabTries(0)\prenom = "Jules" : tabTries(0)\id = 7
tabTries(1)\nom =  "Lager" : tabTries(1)\prenom = "Jérome" : tabTries(1)\id = 12
tabTries(2)\nom =  "Garcia" : tabTries(2)\prenom = "Luca" : tabTries(2)\id = 2

Procedure TriAppel(Critere.s)
  Define i
  Debug Critere
  
  For i = 0 To 2
   Debug  tabTries(i)\nom +" "+tabTries(i)\prenom
 Next  
 
  Select Critere
    Case "Nom"
      SortStructuredArray(tabTries(), #PB_Sort_Ascending, OffsetOf(Person\nom), TypeOf(Person\nom))
    Case "Prenom"
      SortStructuredArray(tabTries(), #PB_Sort_Ascending, OffsetOf(Person\prenom), TypeOf(Person\prenom))
    Case "Id"
      SortStructuredArray(tabTries(), #PB_Sort_Ascending, OffsetOf(Person\id), TypeOf(Person\id))
  EndSelect 
  
EndProcedure

Procedure AfficheListe()
  Define i
  ; vide la liste
  For i = 0 To 2
    RemoveGadgetItem(liste, 0)
  Next
  ; lit les data
  For i = 0 To 2
    AddGadgetItem(liste, -1, tabTries(i)\nom + #LF$ + tabTries(i)\prenom + #LF$ + tabTries(i)\id) 
  Next
EndProcedure


OpenWindow(0, 200, 100, 600, 300, "Disable highlight example")
ListIconGadget(liste, 10, 10, WindowWidth(0) - 20, WindowHeight(0) - 20, "Nom", 110)
AddGadgetColumn(liste, 1, "Prenom", 100)
AddGadgetColumn(liste, 2, "Id", 100)
CocoaMessage(0,  GadgetID(liste), "setAllowsColumnSelection:", #YES) ; autorise la selection de colonne
CocoaMessage(0, GadgetID(liste), "setSelectionHighlightStyle:", -1); -1 pas de surlignement  / surlignement   
AfficheListe()

Repeat
  event = WaitWindowEvent()
  Gadget = EventGadget();
  
  Select Event
    Case #PB_Event_CloseWindow
      quit = 1
    Case #PB_Event_Gadget     
      Select Gadget
          
        Case liste ; liste 
          Define SelectedColumn
          Select  EventType() 
            Case #PB_EventType_LeftDoubleClick                    ; Edite tireur
              Debug "ligne selectionnée"
            Case #PB_EventType_LeftClick   ; clic gauche 
              SelectedColumn = CocoaMessage(0,  GadgetID(Liste) , "selectedColumn")  
              Debug SelectedColumn
              If SelectedColumn = -1
                Debug "Aucune colonne de sélectionnée"
                CocoaMessage(0, GadgetID(liste), "setSelectionHighlightStyle:", 0); -1 pas de surlignement  / surlignement
              Else
                Debug "colonne  sélectionnée"
                ;selection d'une colonne > tri 
                CocoaMessage(0, GadgetID(liste), "setSelectionHighlightStyle:", -1); -1 pas de surlignement  / surlignement
                TriAppel(GetGadgetItemText(Gadget,-1,SelectedColumn))            ;Select SelectedColumn
                AfficheListe()
              EndIf
              
          EndSelect
      EndSelect
      
      EndSelect
    Until quit =1
programme avec bouton

Code : Tout sélectionner

EnableExplicit


Global quit,liste = 10 , event, Gadget, triNom = 11, tripreNom = 12

Structure Person
  nom.s
  prenom.s
  id.i
EndStructure

Global Dim tabTries.Person(2)
tabTries(0)\nom =  "Léger" : tabTries(0)\prenom = "Jules" : tabTries(0)\id = 7
tabTries(1)\nom =  "Leger" : tabTries(1)\prenom = "Jérome" : tabTries(1)\id = 12
tabTries(2)\nom =  "Garcia" : tabTries(2)\prenom = "Luca" : tabTries(2)\id = 2

Procedure TriAppel(Critere.s)
  Define i
  Debug Critere
  
  For i = 0 To 2
   Debug  tabTries(i)\nom +" "+tabTries(i)\prenom
 Next  
  Select Critere
    Case "Nom"
      SortStructuredArray(tabTries(), #PB_Sort_Ascending, OffsetOf(Person\nom), TypeOf(Person\nom))
    Case "Prenom"
      SortStructuredArray(tabTries(), #PB_Sort_Ascending, OffsetOf(Person\prenom), TypeOf(Person\prenom))
    Case "Classement"
      SortStructuredArray(tabTries(), #PB_Sort_Ascending, OffsetOf(Person\id), TypeOf(Person\id))
  EndSelect   
EndProcedure

Procedure AfficheListe()
  Define i
  ; vide la liste
  For i = 0 To 2
    RemoveGadgetItem(liste, 0)
  Next
  ; lit les data
  For i = 0 To 2
    AddGadgetItem(liste, -1, tabTries(i)\nom + #LF$ + tabTries(i)\prenom + #LF$ + tabTries(i)\id) 
  Next
EndProcedure


OpenWindow(0, 200, 100, 600, 300, "Disable highlight example")
ListIconGadget(liste, 10, 40, WindowWidth(0) - 20, WindowHeight(0) - 20, "Nom", 110)
AddGadgetColumn(liste, 1, "Prenom", 100)
AddGadgetColumn(liste, 2, "ID", 100)

 ButtonGadget(triNom , 10 , 3  , 100, 30, "tri nom" )  
 ButtonGadget(triprenom , 110 , 3  , 100, 30, "tri prenom" ) 
 
 AfficheListe()

Repeat
  event = WaitWindowEvent()
  Gadget = EventGadget();
  
  Select Event
    Case #PB_Event_CloseWindow
      quit = 1
    Case #PB_Event_Gadget     
      Select Gadget
        Case triNom
          TriAppel("Nom")
           AfficheListe()
        Case triPrenom
          TriAppel("Prenom")
           AfficheListe()
        Case liste ; liste 
          Define SelectedColumn
          Select  EventType() 
            Case #PB_EventType_LeftDoubleClick  ; Edite tireur
              Debug "ligne selectionnée"
            Case #PB_EventType_LeftClick   ; clic gauche 
          EndSelect
      EndSelect
      
      EndSelect
    Until quit =1
_____________________________________________________________
IMAC 21.5 2012 Core I5 - 2.70 Ghz. 16 GB NVIDIA GeForce GT 640M 512 Mo. MacOs OCPL Sonoma 14.3
MacBook Air M1 - 8Go - Sonoma 14.5

PureBasic 6.11 MacOS
boddhi
Messages : 604
Inscription : lun. 26/avr./2010 16:14
Localisation : S 48° 52' 31'' / O 123° 23' 33''

Re: Tri avec accent

Message par boddhi »

Il n'y a pas, ici, de problème en réalité.
Le tri ne s'effectue pas par caractère mais par code caractère.

Un 'E' a un code (ASCII) égal à 69, un 'e' un code 101, un 'u' un code 117, un 'É' un code 201 et un 'é' un code 223.

Ainsi, lors des opérations de tri sous PB (ou sous SQLite aussi par ex.), le tri se fait selon la valeur numérique attribuée à chaque caractère.
Ce qui donnera avec les lettres précitées :
69 - E, 101 - e, 117 - u, 144 - É, 223 - é
Il est donc normal que 'Jérôme' suive 'Jules' tout comme 'Jérôme' aurait précédé 'jules'.
• J-u = 74-117
• J-é = 74-223
• j-u = 106 - 117

La seule solution est de traiter en amont les chaînes de caractères en remplaçant provisoirement les caractères accentués par leurs équivalents non accentués.

Code : Tout sélectionner

Procedure.s Fc_RemplacementAccents(Chaine.s)
  ReplaceString(Chaine,"é","e",#PB_String_InPlace)
  ReplaceString(Chaine,"í","i",#PB_String_InPlace)
  ReplaceString(Chaine,"ô","o",#PB_String_InPlace)
  ;[ReplaceString(Chaine,"...","...",#PB_String_InPlace)]
  ; etc.
  ProcedureReturn Chaine
EndProcedure

Structure Person
  nom.s
  prenom.s
  id.i
  tri.s
EndStructure

Global Dim tabTries.Person(4)
tabTries(0)\nom =  "Lager" : tabTries(0)\prenom = "Jules" : tabTries(0)\id = 7
tabTries(1)\nom =  "Lager" : tabTries(1)\prenom = "Jérome" : tabTries(1)\id = 12
tabTries(2)\nom =  "Lager" : tabTries(2)\prenom = "jérôme" : tabTries(2)\id = 2
tabTries(3)\nom =  "García" : tabTries(3)\prenom = "Lucas" : tabTries(3)\id = 2
tabTries(4)\nom =  "Garcia" : tabTries(4)\prenom = "luca" : tabTries(4)\id = 2

Define.a Compteur
; Exemple uniquement sur le prénom et tenant compte de la casse
For Compteur=0 To 4
  tabTries(Compteur)\tri=Fc_RemplacementAccents(tabTries(Compteur)\prenom)
Next
SortStructuredArray(tabTries(),#PB_Sort_Ascending,OffsetOf(Person\tri),#PB_String)
For Compteur=0 To 4
  Debug tabTries(Compteur)\nom+" "+tabTries(Compteur)\prenom
Next

; Exemple uniquement sur le prénom et ne tenant pas compte de la casse
Debug ""
For Compteur=0 To 4
  tabTries(Compteur)\tri=LCase(Fc_RemplacementAccents(tabTries(Compteur)\prenom))
Next
SortStructuredArray(tabTries(),#PB_Sort_Ascending,OffsetOf(Person\tri),#PB_String)
For Compteur=0 To 4
  Debug tabTries(Compteur)\nom+" "+tabTries(Compteur)\prenom
Next

; Exemple sur le nom et prénom et ne tenant pas compte de la casse
Debug ""
For Compteur=0 To 4
  tabTries(Compteur)\tri=LCase(Fc_RemplacementAccents(tabTries(Compteur)\nom)+" "+Fc_RemplacementAccents(tabTries(Compteur)\prenom))
Next
SortStructuredArray(tabTries(),#PB_Sort_Ascending,OffsetOf(Person\tri),#PB_String)
For Compteur=0 To 4
  Debug tabTries(Compteur)\nom+" "+tabTries(Compteur)\prenom
Next
Bmld76
Messages : 116
Inscription : dim. 09/janv./2022 12:47

Re: Tri avec accent

Message par Bmld76 »

Merci pour l'explication, je ne m'était pas penché sur la méthode de tri.
_____________________________________________________________
IMAC 21.5 2012 Core I5 - 2.70 Ghz. 16 GB NVIDIA GeForce GT 640M 512 Mo. MacOs OCPL Sonoma 14.3
MacBook Air M1 - 8Go - Sonoma 14.5

PureBasic 6.11 MacOS
Répondre