J'ai essayé tellement de combinaisons d'expressions régulières que je ne sais pas si le problème est mon expression régulière ou mon codage python (étant assez nouveau pour les deux).

J'ai un list appelé inputs:

inputs = [':boy', '_144-', '_1445', '_1445', 'alpha', 'monkey', '#sdakm', '.file', '.magic']

Je veux finir avec un list qui ne contient que les éléments qui ont contiennent un caractère non alphabétique (inconnu).

Je veux donc trouver:

newlist = [':boy', '_144-', '_1445', '#sdakm', '.file', '.magic']

Sans les éléments qui sont tous [a-z]. Je veux également filtrer toutes les correspondances en double (de tout type).

Mon code python est le suivant:

import os, sys, re, string, codecs, cchardet, chardet

inputs = [':boy', '_144-', '_1445', '_1445', 'alpha', 'monkey', '#sdakm', '.file', '.magic']

regex = re.compile('.*[^abcdefghijklmnopqrstuvwxyz]*.*')
myset = set()
inputs_filtered=[]
for inp in inputs:
    if re.search(i,inp):
        if inp not in myset:
            inputs_filtered.append(inp)
            print('adding' + inp)
            myset.add(inp)
            ofile.write(inp + '\n')
        else:
            print('removing duplicate ' + inp)
    else:
        print("IS ALL LETTERS " + i)
print(myset)
ofile.close()

Regex J'ai essayé de filtrer ou de conserver (j'ai essayé tant de façons différentes, y compris différents codes en utilisant des choses comme:

[filter(lambda i: regex.search(i), inputs)]

'\".*[\W|\.|_|\_|-|\-]*.*\"

'.*[^abcdefghijklmnopqrstuvwxyz]*.*'

'\"[\w]*\",?'

'[\w]*'

Une autre chose à ne pas faire est que myset.add() semble produire un ensemble vide mais pour une raison étrange, inputs_filtered est en train d'être rempli ... Je pense.

1
lgjmac 17 avril 2018 à 00:23

4 réponses

Meilleure réponse

Puisque vous utilisez set dans votre exemple, il semble que l'ordre des résultats n'a pas d'importance. Vous pouvez le faire facilement de 2 façons. Un avec regex et l'autre sans regex (pourquoi s'embêter avec regex quand vous n'êtes pas obligé).

Avec regex, vous avez juste besoin d'une simple regex [^a-z]. Avec l'utilisation de filter, vous pouvez effectuer les opérations suivantes:

# drop the IGNORECASE option if you only want lowercase
pat = re.compile(r'[^a-z]', re.IGNORECASE)

# using the function pat.search as your filter function
results = set(filter(pat.search, inputs))

Si cela convient à votre cas, il existe une fonction sur la classe str nommée isalpha qui retourne vrai si votre chaîne n'a que des caractères alpha. Vous pouvez créer votre ensemble à l'aide du code suivant:

results = { word for word in inputs if not word.isalpha() }

Si vous incluez la fonction filterfalse de itertools (le contrepoint de filter), vous pouvez effectuer les opérations suivantes:

from itertools import filterfalse
results = set(filterfalse(str.isalpha, inputs))

Vous pouvez envisager d'écrire votre propre fonction à utiliser avec filter. Voici une fonction qui exclut également les deux-points ou les espaces:

def has_valid_characters(word):
    return not (word.isalpha() or 
                ' ' in word or 
                ':' in word)
# ...
results = set(filter(has_valid_characters, input))

S'il y a un tas d'autres caractères que vous souhaitez exclure, vous pouvez utiliser une expression régulière ou utiliser la fonction any dans le cadre de votre fonction de filtre:

def has_valid_characters_no_regex(word):
    return not (word.isalpha() or
                any(x in word for x in ' :#-'))

pat2 = re.compile('[- :#]')

def has_valid_characters_regex(word):
    return not (word.isalpha() or
                pat2.search(word))
2
black panda 17 avril 2018 à 14:53

Vous pouvez utiliser re.findall avec \W:

inputs = [':boy', '_144-', '_1445', '_1445', 'alpha', 'monkey', '#sdakm', '.file', '.magic']
final_inputs = list(filter(lambda x:re.findall('[\W_]', x), inputs))

Production:

[':boy', '_144-', '_1445', '_1445', '#sdakm', '.file', '.magic']
1
Ajax1234 16 avril 2018 à 21:25

Vous pouvez également essayer sans approche regex:

inputs = [':boy', '_144-', '_1445', '_1445', 'alpha', 'monkey', '#sdakm', '.file', '.magic']


import unicodedata
import sys

symbols=[chr(i) for i in range(sys.maxunicode) if unicodedata.category(chr(i)).startswith('P')]


print([j for i in symbols for j in inputs if i in j])

Production:

['#sdakm', '_144-', '.file', '.magic', ':boy', '_144-', '_1445', '_1445']
0
Aaditya Ura 17 avril 2018 à 04:02

Vous avez un * après [^abcdefghijklmnopqrstuvwxyz], ce qui signifie correspondre à 0 répétition ou plus. Remplacez-le par un + afin que cela signifie qu'il correspond à une ou plusieurs répétitions.

Vous pouvez abréger [^abcdefghijklmnopqrstuvwxyz] en [^a-z].

>>> regex = re.compile('.*[^a-z]+.*')
>>> list(filter(lambda s: regex.match(s), inputs))
[':boy', '_144-', '_1445', '_1445', '#sdakm', '.file', '.magic']
1
fferri 16 avril 2018 à 21:25