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

PyQt Python Discussion :

QtWidgets.QComboBox() effectuer un tri ascendant avec accent


Sujet :

PyQt Python

  1. #1
    Membre actif
    Homme Profil pro
    Animateur Numérique
    Inscrit en
    Février 2013
    Messages
    140
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Animateur Numérique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Février 2013
    Messages : 140
    Points : 208
    Points
    208
    Par défaut QtWidgets.QComboBox() effectuer un tri ascendant avec accent
    Bonjour,

    je n'arrive pas à effectuer un tri ascendant sur une liste passée à un QtWidgets.QComboBox() ou la première lettre du mot possède un accent.

    Dans mon script, je récupère cette liste via une api rest ou l'ascendance n'est pas respectée.

    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
     
    import sys
    from PyQt5 import QtWidgets, QtCore
     
    country_list = ['France', 'Royaume-Uni', 'Géorgie', 'Guinée', 'Indonésie', 'Île de Man', 'Islande', 'Japon', 'Kenya', 'Corée du Sud', 'Kosovo', 'Lesotho', 'Luxembourg', 'Nigéria', 'Suriname', 'Seychelles', 'Îles Turques-et-Caïques', 'Tchad', 'Tuvalu', 'Uganda', 'Uruguay', 'Saint-Vincent-et-les-Grenadines', 'Venezuela', 'Andorre', 'Arménie', 'Antigua-et-Barbuda', 'Azerbaïdjan', 'Burundi', 'Burkina Faso', 'Bangladesh']
     
     
    class Ui_MainWindow(QtWidgets.QMainWindow):
        def __init__(self) -> None:
            super().__init__()
            self.setWindowTitle("Test")
            self.setFixedSize(479, 160)
            self.centralwidget = QtWidgets.QWidget(self)
            self.centralwidget.setObjectName("centralwidget")
            self.comboBox = QtWidgets.QComboBox(self.centralwidget)
            self.comboBox.setGeometry(QtCore.QRect(80, 48, 309, 26))
            self.setCentralWidget(self.centralwidget)
            self.create_items_country()
     
        def create_items_country(self):
            self.comboBox.addItems(country_list)
            self.comboBox.model().sort(0, QtCore.Qt.AscendingOrder)
     
        def display_country(self):
            country = self.comboBox.currentText()
            print(country)
     
     
     
     
    myApp = QtWidgets.QApplication(sys.argv)
    window = Ui_MainWindow()
    window.show()
    sys.exit(myApp.exec_())
    Comment faire pour que [Îles Turques-et-Caïques] ne se retrouve pas à la fin, mais dans les items de [I]

    J'ai trouvé pyuca

    Mais je demande si on ne peut pas faire plus simple.

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 329
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 329
    Points : 36 848
    Points
    36 848
    Par défaut
    Salut,

    Citation Envoyé par Diablo76 Voir le message
    Mais je demande si on ne peut pas faire plus simple.
    Les caractères accentués ne se rangent pas si simplement et leur ordre peut dépendre des pays/régions.
    Mais côté Qt, on devrait pouvoir utiliser QtCore.QCollator (ce qui n'est pas forcément plus simple mais autant utiliser les fonctionnalités de Qt...)

    edit: pour faire plus simple, on peut faire la comparaison sans les accents... mais si c'est assez bon pour une combobox, ça ne va pas être utilisable partout.


    - W

  3. #3
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 201
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 201
    Points : 4 665
    Points
    4 665
    Par défaut
    bonjour

    Et si on ne désire pas utiliser le framework QT (QString.localeAwareCompare le fait aussi ?)...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    from functools import cmp_to_key
    import locale
    country_list = sorted(country_list, key=cmp_to_key(locale.strcoll)))
    EDIT
    ? si cela fonctionne, ce n'est que le code donné pour trier dans la documentation officielle python , en sortie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    ['Andorre', 'Antigua-et-Barbuda', 'Arménie', 'Azerbaïdjan', 'Bangladesh', 
    'Burkina Faso', 'Burundi', 'Corée du Sud', 'France', 'Géorgie', 'Guinée',
    'Île de Man', 'Îles Turques-et-Caïques', 'Indonésie', 'Islande', 'Japon',
    'Kenya', 'Kosovo', 'Lesotho', 'Luxembourg', 'Nigéria', 'Royaume-Uni',
    'Saint-Vincent-et-les-Grenadines', 'Seychelles', 'Suriname', 'Tchad',
    'Tuvalu', 'Uganda', 'Uruguay', 'Venezuela']

  4. #4
    Membre actif
    Homme Profil pro
    Animateur Numérique
    Inscrit en
    Février 2013
    Messages
    140
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Animateur Numérique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Février 2013
    Messages : 140
    Points : 208
    Points
    208
    Par défaut
    Merci wiztricks ,

    Je ne connaissais pas QCollator().

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    from PyQt5 import QtCore
    order = QtCore.QCollator()
     
    country_list = ['France', 'Royaume-Uni', 'Géorgie', 'Guinée', 'Indonésie', 'Île de Man', 'Islande', 'Japon', 'Kenya', 'Corée du Sud', 'Kosovo', 'Lesotho', 'Luxembourg', 'Nigéria', 'Suriname', 'Seychelles', 'Îles Turques-et-Caïques', 'Tchad', 'Tuvalu', 'Uganda', 'Uruguay', 'Saint-Vincent-et-les-Grenadines', 'Venezuela', 'Andorre', 'Arménie', 'Antigua-et-Barbuda', 'Azerbaïdjan', 'Burundi', 'Burkina Faso', 'Bangladesh']
     
    print(sorted(country_list, key=order.sortKey))

  5. #5
    Membre actif
    Homme Profil pro
    Animateur Numérique
    Inscrit en
    Février 2013
    Messages
    140
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Animateur Numérique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Février 2013
    Messages : 140
    Points : 208
    Points
    208
    Par défaut
    Citation Envoyé par papajoker Voir le message
    bonjour

    Et si on ne désire pas utiliser le framework QT (QString.localeAwareCompare le fait aussi ?)...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    from functools import cmp_to_key
    import locale
    country_list = sorted(country_list, key=cmp_to_key(locale.strcoll)))
    Bonjour papajoker,

    Non ça ne fonctionne pas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ['Andorre', 'Antigua-et-Barbuda', 'Arménie', 'Azerbaïdjan', 'Bangladesh', 'Burkina Faso', 'Burundi', 'Corée du Sud', 'France', 'Guinée', 'Géorgie', 'Indonésie', 'Islande', 'Japon', 'Kenya', 'Kosovo', 'Lesotho', 'Luxembourg', 'Nigéria', 'Royaume-Uni', 'Saint-Vincent-et-les-Grenadines', 'Seychelles', 'Suriname', 'Tchad', 'Tuvalu', 'Uganda', 'Uruguay', 'Venezuela', 'Île de Man', 'Îles Turques-et-Caïques']

  6. #6
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 478
    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 478
    Points : 9 278
    Points
    9 278
    Billets dans le blog
    6
    Par défaut
    Bonjour

    Le principe pour intervenir dans l'ordre de tri d'une liste est d'utiliser une fonction qui ajuste la comparaison entre les éléments de la liste.

    Ce que j'utilise maintenant pour trier dans l'ordre alphanumérique français est:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import locale # pour tri selon le dictionnaire français
    locale.setlocale(locale.LC_ALL, ('fr_FR', 'UTF-8'))
     
    ##############################################################################
    def convfr(chaine):
        """convertit la chaine pour la trier selon le dictionnaire français
           demande avant: locale.setlocale(locale.LC_ALL, ('fr_FR', 'UTF-8'))
           exemple de tri français d'une liste': xxx.sort(key=convfr)
        """
        chaine2 = chaine.replace('\xA0', '') # supprime les blancs insécables
        chaine2 = chaine2.replace(' ', '') # supprime les espaces internes
        return locale.strxfrm(chaine2)
    Avec le tri ".sort" de Python, c'est facile:

    L.sort(key=convfr)

    Si on trie une liste de listes, par rapport au 2ème élément des sous-listes:

    L.sort(key=lambda v: convfr(v[1]))

    Avant d'utiliser le module "locale", j'utilisais cela:

    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
    #############################################################################
    alphafr = r""" !"#$%&'()*+,-./0123456789:;<=>?@[\]^_`{|}~ €""" + \
              r"""aAàÀâÂäÄåÅæÆbBcCçÇdDeEéÉèÈêÊëËfFgGhHiIîÎïÏjJ""" + \
              r"""kKlLmMnNoOôÔöÖœŒpPqQrRsStTuUùÙûÛüÜvVwWxXyYÿŸzZ"""
    lgalphafr = len(alphafr)
     
    #############################################################################
    def compalphafr(v1, v2):
        """comparaison de l'ordre alphanumérique des chaines v1 et v2:
           renvoie -1 si v1<v2, 0 si v1==v2, et +1 si v1>v2
           dépendance: alphafr et lgalphafr
        """
        # global alphafr, lgalphafr
        lg1, lg2 = len(v1), len(v2)
        for i in range(0, min([lg1, lg2])):  # min(): mot le + court entre V1 et v2
            i1 = alphafr.find(v1[i])  # indice du caractère v1[i] dans alphafr
            if i1 < 0:
                i1 = lgalphafr + ord(v1[i])  # v1[i] n'est pas dans alphafr
            i2 = alphafr.find(v2[i])  # indice du caractère v2[i] dans alphafr
            if i2 < 0:
                i2 = lgalphafr + ord(v2[i])  # v2[i] n'est pas dans alphafr
            if i1 != i2:
                return (i1 > i2) - (i1 < i2)  # simul. de la fonct. cmp de Python 2
        # les lg 1ers caractères sont identiques: le mot le plus court est avant
        return (lg1 > lg2) - (lg1 < lg2)  # simulation de la fonct. cmp de Python 2
    Cela offre le grand avantage de pouvoir redéfinir l'ordre des caractères si c'est nécessaire, mais il faut l'utiliser avec cmp_to_key de "functools":

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    L.sort(key=cmp_to_key(compalphafr))
    Pour appliquer ça dans PyQt5, il y a une petite discussion qui parle du sujet ici:
    https://www.developpez.net/forums/d2...rting-numbers/

    En gros, il faut modifier une des méthodes __lt__ (=less than) de l'une des classes PyQt5.

  7. #7
    Membre actif
    Homme Profil pro
    Animateur Numérique
    Inscrit en
    Février 2013
    Messages
    140
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Animateur Numérique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Février 2013
    Messages : 140
    Points : 208
    Points
    208
    Par défaut
    Citation Envoyé par papajoker Voir le message

    EDIT
    ? si cela fonctionne, ce n'est que le code donné pour trier dans la documentation officielle python , en sortie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    ['Andorre', 'Antigua-et-Barbuda', 'Arménie', 'Azerbaïdjan', 'Bangladesh', 
    'Burkina Faso', 'Burundi', 'Corée du Sud', 'France', 'Géorgie', 'Guinée',
    'Île de Man', 'Îles Turques-et-Caïques', 'Indonésie', 'Islande', 'Japon',
    'Kenya', 'Kosovo', 'Lesotho', 'Luxembourg', 'Nigéria', 'Royaume-Uni',
    'Saint-Vincent-et-les-Grenadines', 'Seychelles', 'Suriname', 'Tchad',
    'Tuvalu', 'Uganda', 'Uruguay', 'Venezuela']
    Étrange, chez moi ça ne marche pas

    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
     
    Python 3.10.12 (main, Jun 11 2023, 05:26:28) [GCC 11.4.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> from functools import cmp_to_key
    >>> import locale
    >>> 
    >>> country_list = ['France', 'Royaume-Uni', 'Géorgie', 'Guinée', 'Indonésie', 
    'Île de Man', 'Islande', 'Japon', 'Kenya', 'Corée du Sud', 'Kosovo', 'Lesotho', 
    'Luxembourg', 'Nigéria', 'Suriname', 'Seychelles', 'Îles Turques-et-Caïques', 
    'Tchad', 'Tuvalu', 'Uganda', 'Uruguay', 'Saint-Vincent-et-les-Grenadines', 
    'Venezuela', 'Andorre', 'Arménie', 'Antigua-et-Barbuda', 'Azerbaïdjan', 
    'Burundi', 'Burkina Faso', 'Bangladesh']
    >>> 
    >>> country_list = sorted(country_list, key=cmp_to_key(locale.strcoll))
    >>> print(country_list)
     
    ['Andorre', 'Antigua-et-Barbuda', 'Arménie', 'Azerbaïdjan', 'Bangladesh', 
    'Burkina Faso', 'Burundi', 'Corée du Sud', 'France', 'Guinée', 'Géorgie', 
    'Indonésie', 'Islande', 'Japon', 'Kenya', 'Kosovo', 'Lesotho', 'Luxembourg', 
    'Nigéria', 'Royaume-Uni', 'Saint-Vincent-et-les-Grenadines', 
    'Seychelles', 'Suriname', 'Tchad', 'Tuvalu', 'Uganda', 'Uruguay', 
    'Venezuela', 'Île de Man', 'Îles Turques-et-Caïques']
    >>>
    Edit: Peu importe l'OS...

  8. #8
    Membre actif
    Homme Profil pro
    Animateur Numérique
    Inscrit en
    Février 2013
    Messages
    140
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Animateur Numérique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Février 2013
    Messages : 140
    Points : 208
    Points
    208
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Pour appliquer ça dans PyQt5, il y a une petite discussion qui parle du sujet ici:
    https://www.developpez.net/forums/d2...rting-numbers/

    En gros, il faut modifier une des méthodes __lt__ (=less than) de l'une des classes PyQt5.
    Bonjour tyrtamos,

    Oui j'avais vu ça sur SO (la surcharge de __lt__), mais QtCore.QCollator() fait très bien le job

  9. #9
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 478
    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 478
    Points : 9 278
    Points
    9 278
    Billets dans le blog
    6
    Par défaut
    En reprenant l'exemple du 1er post et avec ma solution utilisant le module "locale":

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    country_list = ['France', 'Royaume-Uni', 'Géorgie', 'Guinée', 'Indonésie', 'Île de Man', 'Islande', 'Japon', 'Kenya', 'Corée du Sud', 'Kosovo', 'Lesotho', 'Luxembourg', 'Nigéria', 'Suriname', 'Seychelles', 'Îles Turques-et-Caïques', 'Tchad', 'Tuvalu', 'Uganda', 'Uruguay', 'Saint-Vincent-et-les-Grenadines', 'Venezuela', 'Andorre', 'Arménie', 'Antigua-et-Barbuda', 'Azerbaïdjan', 'Burundi', 'Burkina Faso', 'Bangladesh']
     
    country_list.sort(key=convfr)
     
    for pays in country_list:
        print(pays)
    Ce qui donne:

    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
    Andorre
    Antigua-et-Barbuda
    Arménie
    Azerbaïdjan
    Bangladesh
    Burkina Faso
    Burundi
    Corée du Sud
    France
    Géorgie
    Guinée
    Île de Man
    Îles Turques-et-Caïques
    Indonésie
    Islande
    Japon
    Kenya
    Kosovo
    Lesotho
    Luxembourg
    Nigéria
    Royaume-Uni
    Saint-Vincent-et-les-Grenadines
    Seychelles
    Suriname
    Tchad
    Tuvalu
    Uganda
    Uruguay
    Venezuela
    Il ne reste plus qu'à l'appliquer à PyQt

  10. #10
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 201
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 201
    Points : 4 665
    Points
    4 665
    Par défaut
    Citation Envoyé par Diablo76 Voir le message
    Étrange, chez moi ça ne marche pas
    Edit: Peu importe l'OS...
    Etrange , reste à voir quelle locale tu as sur tes OS ...
    la fonction locale.getlocale() me retourne par défaut ('fr_FR', 'UTF-8'), c'est pour cela que je n'ai pas écrit la ligne "locale.setlocale(locale.LC_ALL, ('fr_FR', 'UTF-8'))" (donnée dans le code de tyrtamos)

    Comme écrit plus haut, ce n'est que le code donné dans la doc

  11. #11
    Membre actif
    Homme Profil pro
    Animateur Numérique
    Inscrit en
    Février 2013
    Messages
    140
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Animateur Numérique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Février 2013
    Messages : 140
    Points : 208
    Points
    208
    Par défaut
    Étrangement les solutions de @papajoker et @tyrtamos fonctionnent bien sous Windows et Linux, mais pas sous OSX

  12. #12
    Membre actif
    Homme Profil pro
    Animateur Numérique
    Inscrit en
    Février 2013
    Messages
    140
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Animateur Numérique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Février 2013
    Messages : 140
    Points : 208
    Points
    208
    Par défaut
    Citation Envoyé par papajoker Voir le message
    Etrange , reste à voir quelle locale tu as sur tes OS ...
    la fonction locale.getlocale() me retourne par défaut ('fr_FR', 'UTF-8'), c'est pour cela que je n'ai pas écrit la ligne "locale.setlocale(locale.LC_ALL, ('fr_FR', 'UTF-8'))" (donnée dans le code de tyrtamos)

    Comme écrit plus haut, ce n'est que le code donné dans la doc
    locale.getlocale() me retourne bien ('fr_FR', 'UTF-8') sous OSX mais ma liste n'est pas triée

    sous Windows, ellle ne retourne ('fr_FR', 'cp1252'), il faut que je précise
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    locale.setlocale(locale.LC_ALL, ("fr_FR", "UTF-8"))
    pour que le tri fonctionne.

  13. #13
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 478
    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 478
    Points : 9 278
    Points
    9 278
    Billets dans le blog
    6
    Par défaut
    Tu peux aussi t'inspirer de la 2ème solution que j'ai donnée qui n'utilise pas "locale". Elle parait plus compliquée mais comme elle est écrite en Python de base, elle est facile à comprendre et à adapter.

  14. #14
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 329
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 329
    Points : 36 848
    Points
    36 848
    Par défaut
    Citation Envoyé par Diablo76 Voir le message
    Étrangement les solutions de @papajoker et @tyrtamos fonctionnent bien sous Windows et Linux, mais pas sous OSX
    locale est implémenté sur chaque environnement avec son interprétation du standard POSIX.
    Python s'appuie sur cet existant sans forcément arriver à masquer les différences. Ce qui n'est pas trop gênant: on peut le faire "au dessus" en reportant le bug.

    - W

  15. #15
    Membre actif
    Homme Profil pro
    Animateur Numérique
    Inscrit en
    Février 2013
    Messages
    140
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Animateur Numérique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Février 2013
    Messages : 140
    Points : 208
    Points
    208
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    locale est implémenté sur chaque environnement avec son interprétation du standard POSIX.
    Python s'appuie sur cet existant sans forcément arriver à masquer les différences. Ce qui n'est pas trop gênant: on peut le faire "au dessus" en reportant le bug.

    - W
    Que veux-tu dire par reporter le bug, car QtCore.QCollator() sait me trier la liste et par défaut, il utilise locale.

  16. #16
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 329
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 329
    Points : 36 848
    Points
    36 848
    Par défaut
    Citation Envoyé par Diablo76 Voir le message
    Que veux-tu dire par reporter le bug, car QtCore.QCollator() sait me trier la liste et par défaut, il utilise locale.
    Pas sûr que Qt n'implémente pas sa propre mouture ou, s'il utilise les implémentations des environnements systèmes, il est peut être plus strict pour offrir une abstraction "homogène" (contrairement à Python).

    - W

  17. #17
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 478
    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 478
    Points : 9 278
    Points
    9 278
    Billets dans le blog
    6
    Par défaut
    J'ai réessayé ma solution sans "locale", mais elle ne donne pas exactement le même ordre qu'avec locale. En effet, je suis parti du principe que chaque caractère accentué est situé APRÈS le même caractère non accentué (donc: 'é' est après le 'e'). Mais si je regarde dans un dictionnaire (papier), je vois qu'il ne tient pas compte de cet ordre: quand il y a un 'é', il le prend comme un 'e', et ce sont les caractères suivants qui déterminent l'ordre des mots comparés. Par exemple avec la liste des pays donnée:

    Avec la solution "locale":

    Île de Man
    Îles Turques-et-Caïques
    Indonésie
    Islande
    et avec la solution sans locale:

    Indonésie
    Islande
    Île de Man
    Îles Turques-et-Caïques
    Si on veut l'ordre du dictionnaire, il faut modifier la solution sans "locale", en supprimant les accents avant la comparaison (encodage unicode seulement!):

    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
    from functools import cmp_to_key
    from unicodedata import normalize, combining # pour supprimer les accents
     
    #############################################################################
    def supaccents(chaine):
        """Supprime les accents de la chaine de caractères 'chaine' (unicode)
           utilise unicodedata.normalize et unicodedata.combining
        """
        chnorm = normalize('NFKD', chaine)
        return "".join([car for car in chnorm if not combining(car)])
     
    #############################################################################
    alphafr = r""" !"#$%&'()*+,-./0123456789:;<=>?@[\]^_`{|}~ €""" + \
              r"""aAàÀâÂäÄåÅæÆbBcCçÇdDeEéÉèÈêÊëËfFgGhHiIîÎïÏjJ""" + \
              r"""kKlLmMnNoOôÔöÖœŒpPqQrRsStTuUùÙûÛüÜvVwWxXyYÿŸzZ"""
    lgalphafr = len(alphafr)
     
    #############################################################################
    def compalphafr(v1, v2):
        """comparaison de l'ordre alphanumérique des chaines v1 et v2:
           renvoie -1 si v1<v2, 0 si v1==v2, et +1 si v1>v2
           dépendance: alphafr et lgalphafr
        """
        # global alphafr, lgalphafr
        v1, v2 = supaccents(v1), supaccents(v2)
        lg1, lg2 = len(v1), len(v2)
        for i in range(0, min([lg1, lg2])):  # min(): mot le + court entre V1 et v2
            i1 = alphafr.find(v1[i])  # indice du caractère v1[i] dans alphafr
            if i1 < 0:
                i1 = lgalphafr + ord(v1[i])  # v1[i] n'est pas dans alphafr
            i2 = alphafr.find(v2[i])  # indice du caractère v2[i] dans alphafr
            if i2 < 0:
                i2 = lgalphafr + ord(v2[i])  # v2[i] n'est pas dans alphafr
            if i1 != i2:
                return (i1 > i2) - (i1 < i2)  # simul. de la fonct. cmp de Python 2
        # les lg 1ers caractères sont identiques: le mot le plus court est avant
        return (lg1 > lg2) - (lg1 < lg2)  # simulation de la fonct. cmp de Python 2
     
    #############################################################################
     
    country_list = ['France', 'Royaume-Uni', 'Géorgie', 'Guinée', 'Indonésie', 'Île de Man', 'Islande', 'Japon', 'Kenya', 'Corée du Sud', 'Kosovo', 'Lesotho', 'Luxembourg', 'Nigéria', 'Suriname', 'Seychelles', 'Îles Turques-et-Caïques', 'Tchad', 'Tuvalu', 'Uganda', 'Uruguay', 'Saint-Vincent-et-les-Grenadines', 'Venezuela', 'Andorre', 'Arménie', 'Antigua-et-Barbuda', 'Azerbaïdjan', 'Burundi', 'Burkina Faso', 'Bangladesh']
     
    country_list = sorted(country_list, key=cmp_to_key(compalphafr))
     
    for pays in country_list:
        print(pays)
    L'ordre redevient le même que celui avec " locale":

    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
    Andorre
    Antigua-et-Barbuda
    Arménie
    Azerbaïdjan
    Bangladesh
    Burkina Faso
    Burundi
    Corée du Sud
    France
    Géorgie
    Guinée
    Île de Man
    Îles Turques-et-Caïques
    Indonésie
    Islande
    Japon
    Kenya
    Kosovo
    Lesotho
    Luxembourg
    Nigéria
    Royaume-Uni
    Saint-Vincent-et-les-Grenadines
    Seychelles
    Suriname
    Tchad
    Tuvalu
    Uganda
    Uruguay
    Venezuela
    Et comme on supprime les accents avant la comparaison, on devrait pouvoir simplifier au moins la variable "alphafr", ce que je ferais si ça t’intéresse.

  18. #18
    Membre actif
    Homme Profil pro
    Animateur Numérique
    Inscrit en
    Février 2013
    Messages
    140
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Animateur Numérique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Février 2013
    Messages : 140
    Points : 208
    Points
    208
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    J'ai réessayé ma solution sans "locale", mais elle ne donne pas exactement le même ordre qu'avec locale. En effet, je suis parti du principe que chaque caractère accentué est situé APRÈS le même caractère non accentué (donc: 'é' est après le 'e'). Mais si je regarde dans un dictionnaire (papier), je vois qu'il ne tient pas compte de cet ordre: quand il y a un 'é', il le prend comme un 'e', et ce sont les caractères suivants qui déterminent l'ordre des mots comparés. Par exemple avec la liste des pays donnée:

    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
    from functools import cmp_to_key
    from unicodedata import normalize, combining # pour supprimer les accents
     
    #############################################################################
    def supaccents(chaine):
        """Supprime les accents de la chaine de caractères 'chaine' (unicode)
           utilise unicodedata.normalize et unicodedata.combining
        """
        chnorm = normalize('NFKD', chaine)
        return "".join([car for car in chnorm if not combining(car)])
     
    #############################################################################
    alphafr = r""" !"#$%&'()*+,-./0123456789:;<=>?@[\]^_`{|}~ €""" + \
              r"""aAàÀâÂäÄåÅæÆbBcCçÇdDeEéÉèÈêÊëËfFgGhHiIîÎïÏjJ""" + \
              r"""kKlLmMnNoOôÔöÖœŒpPqQrRsStTuUùÙûÛüÜvVwWxXyYÿŸzZ"""
    lgalphafr = len(alphafr)
     
    #############################################################################
    def compalphafr(v1, v2):
        """comparaison de l'ordre alphanumérique des chaines v1 et v2:
           renvoie -1 si v1<v2, 0 si v1==v2, et +1 si v1>v2
           dépendance: alphafr et lgalphafr
        """
        # global alphafr, lgalphafr
        v1, v2 = supaccents(v1), supaccents(v2)
        lg1, lg2 = len(v1), len(v2)
        for i in range(0, min([lg1, lg2])):  # min(): mot le + court entre V1 et v2
            i1 = alphafr.find(v1[i])  # indice du caractère v1[i] dans alphafr
            if i1 < 0:
                i1 = lgalphafr + ord(v1[i])  # v1[i] n'est pas dans alphafr
            i2 = alphafr.find(v2[i])  # indice du caractère v2[i] dans alphafr
            if i2 < 0:
                i2 = lgalphafr + ord(v2[i])  # v2[i] n'est pas dans alphafr
            if i1 != i2:
                return (i1 > i2) - (i1 < i2)  # simul. de la fonct. cmp de Python 2
        # les lg 1ers caractères sont identiques: le mot le plus court est avant
        return (lg1 > lg2) - (lg1 < lg2)  # simulation de la fonct. cmp de Python 2
     
    #############################################################################
     
    country_list = ['France', 'Royaume-Uni', 'Géorgie', 'Guinée', 'Indonésie', 'Île de Man', 'Islande', 'Japon', 'Kenya', 'Corée du Sud', 'Kosovo', 'Lesotho', 'Luxembourg', 'Nigéria', 'Suriname', 'Seychelles', 'Îles Turques-et-Caïques', 'Tchad', 'Tuvalu', 'Uganda', 'Uruguay', 'Saint-Vincent-et-les-Grenadines', 'Venezuela', 'Andorre', 'Arménie', 'Antigua-et-Barbuda', 'Azerbaïdjan', 'Burundi', 'Burkina Faso', 'Bangladesh']
     
    country_list = sorted(country_list, key=cmp_to_key(compalphafr))
     
    for pays in country_list:
        print(pays)
    Et comme on supprime les accents avant la comparaison, on devrait pouvoir simplifier au moins la variable "alphafr", ce que je ferais si ça t’intéresse.
    En dehors de QT, J'aime bien ta solution, elle fonctionne sur Mac

  19. #19
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 329
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 329
    Points : 36 848
    Points
    36 848
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Si on veut l'ordre du dictionnaire, il faut modifier la solution sans "locale", en supprimant les accents avant la comparaison (encodage unicode seulement!):
    A mon sens, l'ordre du dictionnaire n'est possible qu'en passant par des "collations": les règles sont fixées par la loi et non par une relation d'ordre. Pour ceux que ça intéresse, il y a de la littérature sur le sujet.

    - W

  20. #20
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 478
    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 478
    Points : 9 278
    Points
    9 278
    Billets dans le blog
    6
    Par défaut
    Depuis que je m'intéresse à ces questions de tri en français, les seuls documents clairs que j'ai trouvés viennent du Québec!

    Par exemple:
    https://www.lirmm.fr/~lafourcade/Sou...-francais.html

    On peut les comprendre. Il ont une telle pression des anglo-saxons qui les entourent qu'il doivent être très rigoureux dans le respect de la langue française. Mais ils ont aussi le sens concret et pratique des anglo-saxons qui rend leur document très facile à comprendre...

Discussions similaires

  1. [SYBASE] Texte avec accents
    Par vsavoir dans le forum Sybase
    Réponses: 6
    Dernier message: 14/02/2005, 16h50
  2. [JavaMail] Pb avec accent dans sujet et corps de l'email
    Par shaun_the_sheep dans le forum API standards et tierces
    Réponses: 7
    Dernier message: 29/10/2004, 12h42
  3. Problème avec accents et CHARACTER SET ISO8859_1
    Par kinda dans le forum InterBase
    Réponses: 13
    Dernier message: 30/10/2003, 15h49
  4. tri obligatoire avec DISTINCT?
    Par Marseillais9 dans le forum Langage SQL
    Réponses: 10
    Dernier message: 31/07/2003, 17h50
  5. PB : affichage de données avec accent sous delphi 6
    Par kinda dans le forum Débuter
    Réponses: 3
    Dernier message: 03/07/2003, 13h19

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