Outils pour utilisateurs

Outils du site


collate_sqlite3

Ceci est une ancienne révision du document !


Comment faire un tri français avec collate

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:

  • 'a' est situé après 'X' (les minuscules sont situées après les majuscules),
  • 'à' est situé après 'x' (les caractères accentués sont situés après les caractères non accentués).

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:

  • un entier <0 si v1<v2
  • 0 si v1==v2
  • un entier >0 si v1>v2

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

Prenons la fonction de comparaison qu'on a déjà sur une autre page de ce site (http://python.jpvweb.com/mesrecettespython/doku.php?id=tris_alpha). On va seulement la modifier dans son titre (compalpha) et dans son encodage (comparaison en 'utf-8' et pas en unicode) :

def compalpha(v1,v2):
    """comparaison des chaines de caractères v1 et v2: 
       renvoie un entier <0 si v1<v2, 0 si v1==v2, un entier >0 si v1>v2
       v1, v2 doivent être en utf-8
    """
    alpha = ur"""!"#$%&'()*+,-./0123456789:;<=>?@""" + \
            ur"""[\]^_`""" + \
            ur"""{|}~ €""" + \
            ur"""aAàÀâÂæÆbBcCçÇdDeEéÉèÈêÊëËfFgGhHiIîÎïÏjJkKlLmMnNoOôÔœŒpPqQrRsStTuUùÙûÛüÜvVwWxXyYÿŸzZ"""
    alpha = alpha.encode('utf-8')
    lgalpha = len(alpha)
    lg1 = len(v1)
    lg2 = len(v2)
    lg = min([lg1,lg2]) # on veut lg=longueur du mot le plus court entre V1 et v2
    for i in range(0,lg):
        i1 = alpha.find(v1[i])
        if i1<0:
            i1 = lgalpha + ord(v1[i])
        i2 = alpha.find(v2[i])
        if i2<0:
            i2 = lgalpha + ord(v2[i])
        if i1<i2:
            return -1
        if i1>i2:
            return 1
    # ici, les lg premiers caractères sont identiques: le mot le plus court est avant l'autre 
    return lg1-lg2

Le principe est simple: c'est vous qui donnez l'ordre de tri avec la définition de la variable alpha. Et les caractères non inclus dans cette variable sont situés après, avec pour indice, l'ordre qu'ils ont dans la police de caractères.


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

xabc
abcç
abcé
Xabcù
Abcè

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

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

Ce qui donne à l'exécution:

Abcè
Xabcù
abcç
abcé
xabc

Vous constatez que ce n'est pas terrible: le 'a' est bien ici après le 'X'…


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

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

Ce qui affiche:

abcç
abcé
Abcè
xabc
Xabcù

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


Amusez-vous bien!

collate_sqlite3.1291366572.txt.gz · Dernière modification: 2010/12/03 09:56 de tyrtamos

Outils de la page