web-dev-qa-db-fra.com

Comment puis-je supprimer toutes les chaînes qui correspondent à certains formats d'une liste?

Question: Disons que j'ai une liste a = ['abd', ' the dog', '4:45 AM', '1234 total', 'etc...','6:31 PM', '2:36']

Comment puis-je supprimer des éléments tels que 4:45 AM et 6:31 PM et '2:36'? c.-à-d. comment puis-je supprimer des éléments de la forme number:number|number et ceux avec AM/PM à la fin?

Pour être honnête, je n'ai pas beaucoup essayé, car je ne sais pas vraiment par où commencer, à part quelque chose comme:

[x for x in a if x != something]
7
cjg123

Vous pouvez utiliser l'expression régulière \d+(?::\d+)?$ et filtrer en l'utilisant.

Voir la démo.

https://regex101.com/r/HoGZYh/1

import re
a = ['abd', ' the dog', '4:45', '1234 total', '123', '6:31']
print [i for i in a if not re.match(r"\d+(?::\d+)?$", i)]

Sortie: ['abd', ' the dog', '1234 total']

11
vks

Pensez à utiliser la fonction filter intégrée avec une expression rationnelle compilée.

>>> import re
>>> no_times = re.compile(r'^(?!\d\d?:\d\d(\s*[AP]M)?$).*$')
>>> a = ['abd', ' the dog', '4:45 AM', '1234 total', 'etc...','6:31 PM', '2:36']

>>> filter(no_times.match, a)
['abd', ' the dog', '1234 total', 'etc...']

Un lambda peut également être utilisé pour le premier argument si, par exemple, vous voulez éviter de compiler une regex, bien que ce soit plus compliqué.

>>> filter(lambda s: not re.match(r'^\d\d?:\d\d(\s*[AP]M)?$', s), a)
['abd', ' the dog', '1234 total', 'etc...']

Notez que dans Python 3, filter renvoie un objet itérable au lieu d’une liste.


L'expression rationnelle ici fonctionne en acceptant toutes les chaînes sauf\d\d?:\d\d(\s*[AP]M)?$. Cela signifie toutes les chaînes sauf celles correspondant à HH:MM, se terminant éventuellement par des espaces suivis de AM ou PM.

2
TehVulpes

Essayez ce code en pur Python . Premièrement, il vérifie les deux derniers caractères, si les deux derniers sont égaux à 'am' ou 'pm', l'élément doit être retiré de la liste . contient ':', si ':' se trouve dans l'élément, il vérifie les caractères avant et après ':'. Si les caractères avant et après ':' sont des chiffres, l'élément est supprimé de la liste. L'idée prend en charge numéro | numéro: numéro et numéro: numéro | numéro.

def removeElements(a):
    removed_elements = []
    L = len(a)
    for i in range(L):
        element = a[i]
        if 'am' == element[-2:].lower() or 'pm' ==element[-2:].lower() :
            removed_elements.append(element)
        if ':' in element:
            part1 = element.split(':')
            part2 = element.split(':')
            if part1[-1].isdigit() and part2[0].isdigit():
                removed_elements.append(element)
    output =  []
    for element in a:
        if not(element in removed_elements):
            output.append(element)
    return output

a = ['abd', ' the dog', '4:45 AM', '1234 total', 'etc...','6:31 PM', '2:36']
output = removeElements(a)
print output

la sortie pour cet exemple est: ['abd', 'le chien', '1234 total', 'etc ...']

2
Pouya

Une regex est la réponse facile.

Voici une alternative avec du Python pur:

>>> a = ['abd', ' the dog', '4:45', '1234 total', 'etc...','6:31', '1234']
>>> [s for s in a if not all(e.isdigit() for e in s.split(':'))]
['abd', ' the dog', '1234 total', 'etc...']

Notez qu'il existe un effet secondaire de '1234'.split(':') qui sert également à filtrer tous les chiffres.


S'il existe une possibilité de '1:2:3' numéros de type:

>>> a = ['abd', ' the dog', '4:45', '1234 total', 'etc...','6:31', '1234', '1:2:3']
>>> [s for s in a if len(s.split(':'))<=2 and not all(e.isdigit() for e in s.split(':'))]
['abd', ' the dog', '1234 total', 'etc...']
1
dawg

Vérifiez cette implémentation.

import re

a = ['abd', ' the dog', '4:45 AM', '1234 total', 'etc...','6:31 PM', '2:36']
regex = re.compile(r'^[0-2]{0,1}[0-9]\:[0-5][0-9]\s{0,1}([AP][M]){0,1}')

a  = [x for x in a if not regex.match(x)]
print(a)

SORTIE

['abd', ' the dog', '1234 total', 'etc...']
1
chandima

L'expression régulière \d:\d\d$ correspond à un chiffre, puis à un :, suivi de deux chiffres.

>>> import re
>>> a = ['abd', ' the dog', '4:45', '1234 total', 'etc...', '6:31']
>>> regex = re.compile('\d:\d\d$')
>>> [s for s in a if regex.match(s)]
['4:45', '6:31']
>>> [s for s in a if not regex.match(s)]
['abd', ' the dog', '1234 total', 'etc...']

\d+:\d+$ correspondrait à n'importe quel nombre n >= 1 de chiffres de chaque côté du :. Je vous suggère de jouer avec ça. La documentation est ici .

Détail: $ spécifie la fin de la chaîne et re.match commence à regarder au début de la chaîne.

1
timgeb

Vous n'avez pas besoin de regex, essayez d'utiliser:

>>> a = ['abd', ' the dog', '4:45 AM', '1234 total', 'etc...','6:31 PM', '2:36']
>>> [i for i in a if ':' not in i and not i[-2:] in ['AM','PM']]
['abd', ' the dog', '1234 total', 'etc...']
>>> 

Ou utilisez une solution beaucoup plus simple avec regex:

>>> import re
>>> a = ['abd', ' the dog', '4:45 AM', '1234 total', 'etc...','6:31 PM', '2:36']
>>> [i for i in a if not re.search('\d+:\d+',i)]
['abd', ' the dog', '1234 total', 'etc...']
>>> 

Ou une version de non-regex qui est aussi beaucoup plus facile:

>>> a = ['abd', ' the dog', '4:45 AM', '1234 total', 'etc...','6:31 PM', '2:36']
>>> [i for i in a if ':' not in i]
['abd', ' the dog', '1234 total', 'etc...']
>>> 
1
U9-Forward