Je débute un peu en Python et en particulier sur le module 're'. J'ai
l'impression que ma programmation est un peu maladroite et je sens que
je pourrais faire autrement mais je ne vois pas trop comment.
Je voulais coder en Python la fonction matlab suivante :
x = strmatch('str', STRS) parcourt le tableau STRS pour trouver les
chaines qui commencent par la chaine str et retourne les indices
correspondants.
et j'ai donc codé ça :
[j for j in range(len(STRS)) if re.match(str, STRS[j])]
Est-ce qu'il n'est pas possible de faire cela de manière plus propre et
plus performante ? J'ai tenté d'utiliser les fonctions map, filter,
where, etc... mais je n'ai rien pondu de valable.
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Bruno Desthuilliers
Bonjour,
Je débute un peu en Python et en particulier sur le module 're'. J'ai l'impression que ma programmation est un peu maladroite et je sens que je pourrais faire autrement mais je ne vois pas trop comment.
Je voulais coder en Python la fonction matlab suivante : x = strmatch('str', STRS) parcourt le tableau STRS pour trouver les chaines qui commencent par la chaine str et retourne les indices correspondants.
et j'ai donc codé ça : [j for j in range(len(STRS)) if re.match(str, STRS[j])]
Est-ce qu'il n'est pas possible de faire cela de manière plus propre et plus performante ? J'ai tenté d'utiliser les fonctions map, filter where, etc... mais je n'ai rien pondu de valable.
Qu'en pensez-vous ?
<convention> Par convention, les identifiants en majuscules sont des (pseudo) constantes... </convention>
Il faudrait verifier avec le profiler, mais a priori, les expressions regulières plombent pas mal les perfs. D'une manière générale, préférer les methodes de l'objet string. Si je reprends ta spec pour strmatch(): -> "> les chaines qui commencent par la chaine str", "".startswith() devrait suffire.
Sinon, enumerate(seq) permet d'itérer "en parallèle" sur les éléments de la séquence *et* leur indice: for indice, item in enumerate(sequence)
bref, une première version serait:
def strmatch(target, strings): return [i for i, s in enumerate(strings) if s.startswith(target)]
Si tu tiens vraiment à utiliser map, filter et autres, tu peux aussi faire ça:
Je te laisse le soin de comparer les perfs respectives (le module timeit est ton ami)
HTH Bruno
Bonjour,
Je débute un peu en Python et en particulier sur le module 're'. J'ai
l'impression que ma programmation est un peu maladroite et je sens que
je pourrais faire autrement mais je ne vois pas trop comment.
Je voulais coder en Python la fonction matlab suivante :
x = strmatch('str', STRS) parcourt le tableau STRS pour trouver les
chaines qui commencent par la chaine str et retourne les indices
correspondants.
et j'ai donc codé ça :
[j for j in range(len(STRS)) if re.match(str, STRS[j])]
Est-ce qu'il n'est pas possible de faire cela de manière plus propre et
plus performante ? J'ai tenté d'utiliser les fonctions map, filter
where, etc... mais je n'ai rien pondu de valable.
Qu'en pensez-vous ?
<convention>
Par convention, les identifiants en majuscules sont des (pseudo)
constantes...
</convention>
Il faudrait verifier avec le profiler, mais a priori, les expressions
regulières plombent pas mal les perfs. D'une manière générale, préférer
les methodes de l'objet string. Si je reprends ta spec pour strmatch():
-> "> les chaines qui commencent par la chaine str", "".startswith()
devrait suffire.
Sinon, enumerate(seq) permet d'itérer "en parallèle" sur les éléments de
la séquence *et* leur indice:
for indice, item in enumerate(sequence)
bref, une première version serait:
def strmatch(target, strings):
return [i for i, s in enumerate(strings) if s.startswith(target)]
Si tu tiens vraiment à utiliser map, filter et autres, tu peux aussi
faire ça:
Je débute un peu en Python et en particulier sur le module 're'. J'ai l'impression que ma programmation est un peu maladroite et je sens que je pourrais faire autrement mais je ne vois pas trop comment.
Je voulais coder en Python la fonction matlab suivante : x = strmatch('str', STRS) parcourt le tableau STRS pour trouver les chaines qui commencent par la chaine str et retourne les indices correspondants.
et j'ai donc codé ça : [j for j in range(len(STRS)) if re.match(str, STRS[j])]
Est-ce qu'il n'est pas possible de faire cela de manière plus propre et plus performante ? J'ai tenté d'utiliser les fonctions map, filter where, etc... mais je n'ai rien pondu de valable.
Qu'en pensez-vous ?
<convention> Par convention, les identifiants en majuscules sont des (pseudo) constantes... </convention>
Il faudrait verifier avec le profiler, mais a priori, les expressions regulières plombent pas mal les perfs. D'une manière générale, préférer les methodes de l'objet string. Si je reprends ta spec pour strmatch(): -> "> les chaines qui commencent par la chaine str", "".startswith() devrait suffire.
Sinon, enumerate(seq) permet d'itérer "en parallèle" sur les éléments de la séquence *et* leur indice: for indice, item in enumerate(sequence)
bref, une première version serait:
def strmatch(target, strings): return [i for i, s in enumerate(strings) if s.startswith(target)]
Si tu tiens vraiment à utiliser map, filter et autres, tu peux aussi faire ça:
Je te laisse le soin de comparer les perfs respectives (le module timeit est ton ami)
HTH Bruno
tiissa
Bruno Desthuilliers wrote:
[j for j in range(len(STRS)) if re.match(str, STRS[j])]
Il faudrait verifier avec le profiler, mais a priori, les expressions
regulières plombent pas mal les perfs. D'une manière générale, préférer les methodes de l'objet string. Si je reprends ta spec pour strmatch(): -> "> les chaines qui commencent par la chaine str", "".startswith() devrait suffire.
Sinon, s'il faut vraiment une expression régulière, il est peut-être intéressant de la compiler une fois pour toute (non testé) :
def strmatch(target, strings): maregexp = re.compile(target) return [i for i, s in enumerate(STRS) if maregexp.match(s)]
Ensuite, si les performances sont vraiment un problème, il faut en effet vérifier dans le profiler et toutes ces sortes de choses. Sinon, ça me semble acceptable.
Accessoirement, les map, filter, ... sont une autre manière de faire la même chose avec une approche plus fonctionnelle (d'où le préfixe lisp). Mais les 'list comprehensions' ne sont pas moins propres et sont peut-être même plus pythonesque, puisqu'il semble que GvR veuille supprimer map et consorts de python 3000.
Bruno Desthuilliers wrote:
[j for j in range(len(STRS)) if re.match(str, STRS[j])]
Il faudrait verifier avec le profiler, mais a priori, les expressions
regulières plombent pas mal les perfs. D'une manière générale, préférer
les methodes de l'objet string. Si je reprends ta spec pour strmatch():
-> "> les chaines qui commencent par la chaine str", "".startswith()
devrait suffire.
Sinon, s'il faut vraiment une expression régulière, il est peut-être
intéressant de la compiler une fois pour toute (non testé) :
def strmatch(target, strings):
maregexp = re.compile(target)
return [i for i, s in enumerate(STRS) if maregexp.match(s)]
Ensuite, si les performances sont vraiment un problème, il faut en effet
vérifier dans le profiler et toutes ces sortes de choses. Sinon, ça me
semble acceptable.
Accessoirement, les map, filter, ... sont une autre manière de faire la
même chose avec une approche plus fonctionnelle (d'où le préfixe lisp).
Mais les 'list comprehensions' ne sont pas moins propres et sont
peut-être même plus pythonesque, puisqu'il semble que GvR veuille
supprimer map et consorts de python 3000.
[j for j in range(len(STRS)) if re.match(str, STRS[j])]
Il faudrait verifier avec le profiler, mais a priori, les expressions
regulières plombent pas mal les perfs. D'une manière générale, préférer les methodes de l'objet string. Si je reprends ta spec pour strmatch(): -> "> les chaines qui commencent par la chaine str", "".startswith() devrait suffire.
Sinon, s'il faut vraiment une expression régulière, il est peut-être intéressant de la compiler une fois pour toute (non testé) :
def strmatch(target, strings): maregexp = re.compile(target) return [i for i, s in enumerate(STRS) if maregexp.match(s)]
Ensuite, si les performances sont vraiment un problème, il faut en effet vérifier dans le profiler et toutes ces sortes de choses. Sinon, ça me semble acceptable.
Accessoirement, les map, filter, ... sont une autre manière de faire la même chose avec une approche plus fonctionnelle (d'où le préfixe lisp). Mais les 'list comprehensions' ne sont pas moins propres et sont peut-être même plus pythonesque, puisqu'il semble que GvR veuille supprimer map et consorts de python 3000.
Bruno Desthuilliers
(snip)
Accessoirement, les map, filter, ... sont une autre manière de faire la même chose avec une approche plus fonctionnelle (d'où le préfixe lisp).
<mode="j'etale ma science"> les listes en intention viennent aussi de la programmation fonctionelle (de Haskell, qui est bien plus purement fonctionnel que Common Lisp). </mode>
Etonnant, non ?-)
Bruno
(snip)
Accessoirement, les map, filter, ... sont une autre manière de faire la
même chose avec une approche plus fonctionnelle
(d'où le préfixe lisp).
<mode="j'etale ma science">
les listes en intention viennent aussi de la programmation fonctionelle
(de Haskell, qui est bien plus purement fonctionnel que Common Lisp).
</mode>
Accessoirement, les map, filter, ... sont une autre manière de faire la même chose avec une approche plus fonctionnelle (d'où le préfixe lisp).
<mode="j'etale ma science"> les listes en intention viennent aussi de la programmation fonctionelle (de Haskell, qui est bien plus purement fonctionnel que Common Lisp). </mode>
Etonnant, non ?-)
Bruno
Bernard
On Thu, 14 Jul 2005 18:19:53 +0200, Bruno Desthuilliers
Je voulais coder en Python la fonction matlab suivante : x = strmatch('str', STRS) parcourt le tableau STRS pour trouver les chaines qui commencent par la chaine str et retourne les indices correspondants.
et j'ai donc codé ça : [j for j in range(len(STRS)) if re.match(str, STRS[j])]
Il faudrait verifier avec le profiler, mais a priori, les expressions regulières plombent pas mal les perfs. D'une manière générale, préférer les methodes de l'objet string. Si je reprends ta spec pour strmatch(): -> "> les chaines qui commencent par la chaine str", "".startswith() devrait suffire.
Bon sang j'avais pourtant bien lu le manuel de long en large et toute la section sur 'string' et 're' et cela ne m'était même pas venu à l'esprit de regarder les méthodes de string... Comme quoi je n'ai pas fini d'apprendre...
Sinon, enumerate(seq) permet d'itérer "en parallèle" sur les éléments de la séquence *et* leur indice: for indice, item in enumerate(sequence)
Je ne connaissais pas, merci ! Il n'y a pas de pages regroupant ce genre d'astuces par hasard ?
bref, une première version serait:
def strmatch(target, strings): return [i for i, s in enumerate(strings) if s.startswith(target)]
Impeccable, je la garde !
Si tu tiens vraiment à utiliser map, filter et autres, tu peux aussi faire ça:
Je te laisse le soin de comparer les perfs respectives (le module timeit est ton ami)
Je ne cherche pas la performance à tout prix, mais la version que tu m'as donné en premier a l'énorme avantage de ne pas importer de module supplémentaire, en plus d'être lisible (car avec map et filter...). Je la garde donc !
Merci pour toutes ces recommandations !
On Thu, 14 Jul 2005 18:19:53 +0200, Bruno Desthuilliers
Je voulais coder en Python la fonction matlab suivante :
x = strmatch('str', STRS) parcourt le tableau STRS pour trouver les
chaines qui commencent par la chaine str et retourne les indices
correspondants.
et j'ai donc codé ça :
[j for j in range(len(STRS)) if re.match(str, STRS[j])]
Il faudrait verifier avec le profiler, mais a priori, les expressions
regulières plombent pas mal les perfs. D'une manière générale,
préférer les methodes de l'objet string. Si je reprends ta spec pour
strmatch(): -> "> les chaines qui commencent par la chaine str",
"".startswith() devrait suffire.
Bon sang j'avais pourtant bien lu le manuel de long en large et toute la
section sur 'string' et 're' et cela ne m'était même pas venu à l'esprit
de regarder les méthodes de string...
Comme quoi je n'ai pas fini d'apprendre...
Sinon, enumerate(seq) permet d'itérer "en parallèle" sur les éléments
de la séquence *et* leur indice:
for indice, item in enumerate(sequence)
Je ne connaissais pas, merci !
Il n'y a pas de pages regroupant ce genre d'astuces par hasard ?
bref, une première version serait:
def strmatch(target, strings):
return [i for i, s in enumerate(strings) if s.startswith(target)]
Impeccable, je la garde !
Si tu tiens vraiment à utiliser map, filter et autres, tu peux aussi
faire ça:
Je te laisse le soin de comparer les perfs respectives (le module
timeit est ton ami)
Je ne cherche pas la performance à tout prix, mais la version que tu
m'as donné en premier a l'énorme avantage de ne pas importer de module
supplémentaire, en plus d'être lisible (car avec map et filter...).
Je la garde donc !
On Thu, 14 Jul 2005 18:19:53 +0200, Bruno Desthuilliers
Je voulais coder en Python la fonction matlab suivante : x = strmatch('str', STRS) parcourt le tableau STRS pour trouver les chaines qui commencent par la chaine str et retourne les indices correspondants.
et j'ai donc codé ça : [j for j in range(len(STRS)) if re.match(str, STRS[j])]
Il faudrait verifier avec le profiler, mais a priori, les expressions regulières plombent pas mal les perfs. D'une manière générale, préférer les methodes de l'objet string. Si je reprends ta spec pour strmatch(): -> "> les chaines qui commencent par la chaine str", "".startswith() devrait suffire.
Bon sang j'avais pourtant bien lu le manuel de long en large et toute la section sur 'string' et 're' et cela ne m'était même pas venu à l'esprit de regarder les méthodes de string... Comme quoi je n'ai pas fini d'apprendre...
Sinon, enumerate(seq) permet d'itérer "en parallèle" sur les éléments de la séquence *et* leur indice: for indice, item in enumerate(sequence)
Je ne connaissais pas, merci ! Il n'y a pas de pages regroupant ce genre d'astuces par hasard ?
bref, une première version serait:
def strmatch(target, strings): return [i for i, s in enumerate(strings) if s.startswith(target)]
Impeccable, je la garde !
Si tu tiens vraiment à utiliser map, filter et autres, tu peux aussi faire ça:
Je te laisse le soin de comparer les perfs respectives (le module timeit est ton ami)
Je ne cherche pas la performance à tout prix, mais la version que tu m'as donné en premier a l'énorme avantage de ne pas importer de module supplémentaire, en plus d'être lisible (car avec map et filter...). Je la garde donc !
Merci pour toutes ces recommandations !
Bernard
[j for j in range(len(STRS)) if re.match(str, STRS[j])]
Il faudrait verifier avec le profiler, mais a priori, les
expressions regulières plombent pas mal les perfs. D'une manière générale, préférer les methodes de l'objet string. Si je reprends ta spec pour strmatch(): -> "> les chaines qui commencent par la chaine str", "".startswith() devrait suffire.
Sinon, s'il faut vraiment une expression régulière, il est peut-être intéressant de la compiler une fois pour toute (non testé) :
def strmatch(target, strings): maregexp = re.compile(target) return [i for i, s in enumerate(STRS) if maregexp.match(s)]
Oui c'est même ce qui est recommandé dans le manuel sur 're'
Ensuite, si les performances sont vraiment un problème, il faut en effet vérifier dans le profiler et toutes ces sortes de choses. Sinon, ça me semble acceptable.
Moi aussi !
Accessoirement, les map, filter, ... sont une autre manière de faire la même chose avec une approche plus fonctionnelle (d'où le préfixe lisp). Mais les 'list comprehensions' ne sont pas moins propres et sont peut-être même plus pythonesque, puisqu'il semble que GvR veuille supprimer map et consorts de python 3000.
J'avais lu une page sur l'optimisation des boucles en Python et les 'list comprehensions' étaient moins rapides que les map et filter... Impossible de retrouver la page cependant...
[j for j in range(len(STRS)) if re.match(str, STRS[j])]
Il faudrait verifier avec le profiler, mais a priori, les
expressions regulières plombent pas mal les perfs. D'une manière
générale, préférer les methodes de l'objet string. Si je reprends
ta spec pour strmatch(): -> "> les chaines qui commencent par la
chaine str", "".startswith() devrait suffire.
Sinon, s'il faut vraiment une expression régulière, il est peut-être
intéressant de la compiler une fois pour toute (non testé) :
def strmatch(target, strings):
maregexp = re.compile(target)
return [i for i, s in enumerate(STRS) if maregexp.match(s)]
Oui c'est même ce qui est recommandé dans le manuel sur 're'
Ensuite, si les performances sont vraiment un problème, il faut en
effet vérifier dans le profiler et toutes ces sortes de choses.
Sinon, ça me semble acceptable.
Moi aussi !
Accessoirement, les map, filter, ... sont une autre manière de faire
la même chose avec une approche plus fonctionnelle (d'où le préfixe
lisp). Mais les 'list comprehensions' ne sont pas moins propres et
sont peut-être même plus pythonesque, puisqu'il semble que GvR
veuille supprimer map et consorts de python 3000.
J'avais lu une page sur l'optimisation des boucles en Python et les
'list comprehensions' étaient moins rapides que les map et filter...
Impossible de retrouver la page cependant...
[j for j in range(len(STRS)) if re.match(str, STRS[j])]
Il faudrait verifier avec le profiler, mais a priori, les
expressions regulières plombent pas mal les perfs. D'une manière générale, préférer les methodes de l'objet string. Si je reprends ta spec pour strmatch(): -> "> les chaines qui commencent par la chaine str", "".startswith() devrait suffire.
Sinon, s'il faut vraiment une expression régulière, il est peut-être intéressant de la compiler une fois pour toute (non testé) :
def strmatch(target, strings): maregexp = re.compile(target) return [i for i, s in enumerate(STRS) if maregexp.match(s)]
Oui c'est même ce qui est recommandé dans le manuel sur 're'
Ensuite, si les performances sont vraiment un problème, il faut en effet vérifier dans le profiler et toutes ces sortes de choses. Sinon, ça me semble acceptable.
Moi aussi !
Accessoirement, les map, filter, ... sont une autre manière de faire la même chose avec une approche plus fonctionnelle (d'où le préfixe lisp). Mais les 'list comprehensions' ne sont pas moins propres et sont peut-être même plus pythonesque, puisqu'il semble que GvR veuille supprimer map et consorts de python 3000.
J'avais lu une page sur l'optimisation des boucles en Python et les 'list comprehensions' étaient moins rapides que les map et filter... Impossible de retrouver la page cependant...