2010-08-18 8 views
8

Je fais un filtre dans lequel je vérifie si une chaîne unicode (encodage utf-8) ne contient pas de caractères majuscules (dans toutes les langues). Cela me convient si la chaîne ne contient aucun caractère.Python: Comment vérifier si une chaîne unicode contient un caractère cased?

Par exemple: 'Bonjour!' ne passera pas le filtre, mais "!" devrait passer le filtre, puisque "!" n'est pas un personnage encapsulé.

J'ai prévu d'utiliser la méthode islower(), mais dans l'exemple ci-dessus, "!". Islower() retournera False. Selon la documentation Python, "La méthode python unicode islower() renvoie True si les caractères encapsulés de la chaîne unicode sont en minuscules et que la chaîne contient au moins un caractère encapsulé, sinon elle renvoie False."

Depuis la méthode renvoie également False lorsque la chaîne ne contient aucun caractère cased, à savoir. "!", Je veux vérifier si la chaîne contient un caractère quelconque.

Quelque chose comme ça ....

string = unicode("[email protected]#$%^", 'utf-8') 

#check first if it contains cased characters 
if not contains_cased(string): 
    return True 

return string.islower(): 

Toutes les suggestions pour une fonction contains_cased()?

Ou probablement une approche de mise en œuvre différente?

Merci!

+0

La réponse que vous avez acceptée semble être incorrecte. Vois ma réponse. –

Répondre

6

Here est le scoop complet sur les catégories de caractères Unicode.

catégories de lettres comprennent:

Ll -- lowercase 
Lu -- uppercase 
Lt -- titlecase 
Lm -- modifier 
Lo -- other 

Notez que Ll <-> islower(); de même pour Lu; (Lu or Lt) <-> istitle()

Vous pouvez lire la discussion compliquée sur le boîtier, qui comprend une discussion de Lm lettres.

Le traitement en aveugle de toutes les «lettres» sous forme de boîtier est manifestement erroné. La catégorie Lo inclut 45301 points de code dans le BMP (compté en utilisant Python 2.6). Une grande partie d'entre eux seraient Hangul Syllables, les idéogrammes CJK, et d'autres caractères est-asiatique - très difficile de comprendre comment ils pourraient être considérés comme "casé".

Vous pourriez envisager une définition alternative, basée sur le comportement (non spécifié) de "caractères en casse" que vous attendez. Voici simple première tentative:

>>> cased = lambda c: c.upper() != c or c.lower() != c 
>>> sum(cased(unichr(i)) for i in xrange(65536)) 
1970 
>>> 

Fait intéressant il y a 1216 x 937 x et Ll Lu, un total de 2153 ...la portée d'une enquête plus approfondie sur ce que Ll et Lu signifient vraiment.

+0

@John: Wow. Merci pour votre explication. Il m'a fallu du temps pour le comprendre. J'ai regardé votre lien, et je pense que je dois l'étudier plus en détail. J'ai le sentiment que ce que je vais découvrir va me faire refaire une grande partie de mon code. Yikes. Merci! – Albert

+0

@Albert: Ne paniquez pas. Comme je l'ai laissé entendre, d'abord développer une définition de ce que vous entendez par «cased». Quel traitement différent appliquerez-vous aux chars cased par opposition aux chars uncased? Ma définition d'exemple était "char qui a un" partenaire "majuscule ou minuscule" ". Certains (peut-être tous) de la différence entre les caractères de 1970 et le 2153 semblent être dus à des caractères qui sont classés comme «Ll» parce qu'ils ressemblent à un caractère en minuscule, mais n'ont pas de partenaire «Lu», et vice versa - Vous devez décider si ceux-ci sont "enveloppés" pour vos besoins. BTW vous pouvez changer votre réponse acceptée :-) –

+0

@John: Eh bien, je suis en train de faire une API pour mon service web. Mon service Web accepte une clé qui correspond à un enregistrement spécifique dans ma base de données. La clé est sensible à la casse et la clé peut être composée de n'importe quel caractère unicode. Donc, afin de normaliser toutes les entrées, je vais convertir toutes les requêtes clés en minuscules (si elles ont des équivalents en majuscules). Une conséquence de cela est lorsque je crée les clés d'enregistrement (que mes utilisateurs peuvent personnaliser), je ne peux pas accepter n'importe quel caractère majuscule qui peut être converti en un minuscule équivalent par la fonction toLower(). Donc j'essaye de faire un filtre pour ça. Aucune suggestion? – Albert

7
import unicodedata as ud 

def contains_cased(u): 
    return any(ud.category(c)[0] == 'L' for c in u) 
+0

Arg alex, y a-t-il quelque chose que vous ne connaissez pas? –

+2

-1 Traite les caractères est-asiatiques comme "cased". Vois ma réponse. –

+0

+1: solution de travail (par rapport à la bonne explication sans code exécutable de John Machin) – oDDsKooL

1

module utilisation unicodedata,

unicodedata.category(character) 

renvoie "Ll" pour les lettres minuscules et "Lu" pour les majuscules.

here vous trouverez la liste des catégories de caractères unicode

Questions connexes