Table des matières

Comment faire un tri français avec collate

[Refonte de la page le 3/3/2015. Passage à Python 3]

Problématique

Quand on veut extraire d'une base SQL des informations texte triées en utilisant 'ORDER BY', on se heurte au problème habituel: l'ordre de tri coïncide avec l'ordre des caractères dans les polices de caractères, c'est à dire, par exemple, que:

Solution

Pour trier selon l'alphabet français, et en fait, selon l'alphabet qu'on veut, on va créer une fonction de comparaison comme cmp(v1, v2), c'est à dire qui compare v1 et v2 et qui renvoie:

Ceci, comme on peut le faire avec la méthode sort() du Python.

Voilà le code proposé (Python 3):

import locale
 
#############################################################################
class Compdicofr(object):
    """comparaison de 2 chaines selon le dictionnaire français"""
 
    def __init__(self):
        self.loc = locale.getlocale()  # stocke la locale courante
        self.espinsec = '\xA0'  # espace insécable
 
    def __call__(self, v1, v2):
 
        # on retire les tirets et les blancs insécables
        v1 = v1.replace('-', '')
        v1 = v1.replace(self.espinsec, '')
        v2 = v2.replace('-', '')
        v2 = v2.replace(self.espinsec, '')
 
        # on fait la comparaison selon la locale
        locale.setlocale(locale.LC_ALL, '')
        comp = locale.strcoll(v1, v2)
 
        # retour à la locale initiale
        locale.setlocale(locale.LC_ALL, self.loc)
 
        # on retourne le résultat de la comparaison
        return comp
 
compdicofr = Compdicofr()


Prenons maintenant un exemple: on crée une base sqlite3 contenant une table “test” avec un champ “mots” contenant dans l'ordre d'introduction:

xabc
abcç
abcé
Xabcù
Abcè
êqsdf

Voilà le code pour extraire ces données et les présenter dans l'ordre de tri habituel:

cur.execute("""
    SELECT *
    FROM test 
    ORDER BY mot
    """)
datas = cur.fetchall()
 
for data in datas:
    print data[0]

Ce qui donne à l'exécution:

Abcè
Xabcù
abcç
abcé
xabc
êqsdf

Vous constatez que ce n'est pas terrible: le 'a' est après le 'X' et le 'ê' est après le 'x'…


Voilà maintenant le code qui permet de trier dans le bon ordre:

cnx.create_collation("compdicofr", compdicofr)
 
cur.execute("""
    SELECT *
    FROM test 
    ORDER BY mot COLLATE compdicofr
    """)
datas = cur.fetchall()
 
for data in datas:
    print data[0]

Ce qui affiche:

abcç
abcé
Abcè
êqsdf
xabc
Xabcù

C'est quand même autre chose, non?


Amusez-vous bien!