Outils pour utilisateurs

Outils du site


collate_sqlite3

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:

  • '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.

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!

collate_sqlite3.txt · Dernière modification: 2015/03/03 17:55 par tyrtamos

Outils de la page