Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Itérer sur une liste privée de certains éléments.

2 views
Skip to first unread message

Kaoron

unread,
Nov 6, 2009, 4:55:38 AM11/6/09
to
Bonjour,

Pouvez-vous m'enrichir d'une m�thode �l�gante pour it�rer sur une liste
priv�e de certains de ses �l�ments ?

La solution que j'emploie actuellement est celle-ci :
>for e in list1 :
> if not e in list2 :
> <instructions>

Elle a le d�savantage de diviser la d�finition de mon ensemble it�r� sur
deux instructions, et d'approfondir inutilement l'indentation.


J'avais envisag� les listes en intention, ce qui me donnait ceci :
>for e in [e for e in list1 if e not in list2]:
> <instructions>

Mais comme vous pouvez l'appr�cier, �a n'a plus grand chose de lisible.


La syntaxe suivante d�riv�e des listes en intention ne fonctionne pas :
>for e in list1 if e not in list2 :

Avez-vous une meilleure solution � me proposer ?

Alain BARTHE

unread,
Nov 6, 2009, 5:06:42 AM11/6/09
to
Kaoron a �crit :

Tu peux essayer :

for e in filter (<fonction>, list1):
<instruction>

Avec <fonction> qui peut �tre une fonction bool�enne qui fasse ton
filtrage (si cette fonction existe d�j�) ou une lambda expression si tu
ne veux pas surcharger ton espace de noms.

Ex:

for e in filter (lambda x: x not in list2, list1):
<instruction>

Le gain n'est quand m�me pas �norme par rapport � la syntaxe initiale.

Alain BARTHE

unread,
Nov 6, 2009, 5:18:33 AM11/6/09
to
Kaoron a �crit :

> Bonjour,
>
> Pouvez-vous m'enrichir d'une m�thode �l�gante pour it�rer sur une liste
> priv�e de certains de ses �l�ments ?
>
> La solution que j'emploie actuellement est celle-ci :
> >for e in list1 :
> > if not e in list2 :
> > <instructions>
>
> Elle a le d�savantage de diviser la d�finition de mon ensemble it�r� sur
> deux instructions, et d'approfondir inutilement l'indentation.
>
Ca va surement en faire hurler plus d'un mais j'aime bien
(et puis c'est vendredi) :

for e in list1:
if e in list2: continue
<instructions-sans-approfondir-inutilement-l-indentation>

J'adore faire des trucs comme �a dans les boucles :
on peut mettre plein de tests en d�but de boucle, pour ignorer toute une
s�rie de cas, sans approfondir inutilement...

Ca �vite parfois de se retrouver avec le bloc d'instructions "utiles"
perdu dans une 3eme, 4eme niveau d'indentation, ce qui n'est pas
forc�ment plus lisible que quelques instructions continue bien
identifi�es en d�but de boucle.

Pierre Maurette

unread,
Nov 6, 2009, 5:37:53 AM11/6/09
to
Kaoron, le 06/11/2009 a ᅵcrit :
> Bonjour,
>
> Pouvez-vous m'enrichir d'une mᅵthode ᅵlᅵgante pour itᅵrer sur une liste
> privᅵe de certains de ses ᅵlᅵments ?

>
> La solution que j'emploie actuellement est celle-ci :
> >for e in list1 :
> > if not e in list2 :
> > <instructions>
>
> Elle a le dᅵsavantage de diviser la dᅵfinition de mon ensemble itᅵrᅵ sur deux
> instructions, et d'approfondir inutilement l'indentation.

Mais elle a l'avantage d'ᅵtre maintenable sans risque de casser
vicieusement un truc qui marche. Je suis revenu de mon ᅵpoque "tout
doiot tenir sur une seule ligne" qui me gᅵnᅵrait des trucs qui me
prenaient dix minutes ᅵ dᅵtricoter pour modifier par exemple un test.
Les deux trucs proposᅵs par Alain BARTHE sont parfaits sur le plan de
la maintenabilitᅵ.

> J'avais envisagᅵ les listes en intention, ce qui me donnait ceci :


> >for e in [e for e in list1 if e not in list2]:
> > <instructions>
>

> Mais comme vous pouvez l'apprᅵcier, ᅵa n'a plus grand chose de lisible.

Si vous trouvez ᅵa illisible, le problᅵme est peut-ᅵtre chez vous ;-)
Vous pouvez compacter, et pour moi ᅵa reste trᅵs lisible:

[instructions(_) for _ in list1 if _ not in list2]
ou
[instructions(_) for _ in filter(<fonction>, list1)]

Selon ce que fait <instructions> vous codez une fonction ou utilisez un
lambda. Vous pouvez aussi regarder du cotᅵ de map et reduce.

Je me rᅵpᅵte, j'ai perdu pas mal de temps ᅵ chercher ᅵ coder ᅵlᅵgant.
Rᅵsultat, je perdais du temps, ce n'ᅵtait *pas* ᅵlᅵgant parce
qu'illisible, bref, j'ai changᅵ mon fusil d'ᅵpaule et je vais au plus
rapide et naturel. A vous de voir...

> La syntaxe suivante dᅵrivᅵe des listes en intention ne fonctionne pas :


> >for e in list1 if e not in list2 :
>

> Avez-vous une meilleure solution ᅵ me proposer ?

--
Pierre Maurette


PIGUET Bruno

unread,
Nov 6, 2009, 7:42:50 AM11/6/09
to
Le Fri, 06 Nov 2009 10:55:38 +0100, Kaoron a écrit :

> Bonjour,
>
> Pouvez-vous m'enrichir d'une méthode élégante pour itérer sur une liste
> privée de certains de ses éléments ?


>
> La solution que j'emploie actuellement est celle-ci :
> >for e in list1 :
> > if not e in list2 :
> > <instructions>
>

Est-ce une situation où il est possible d'utiliser les ensembles
("sets") ?

Dans un cas simple, j'ai remplacé :
l5 = range(5, 1000, 5)
l3 = range(3, 1000, 3)
l = l3
for i in l5:
if not i in l3:
l.append(i)

par :
s5 = set(range(5, 1000, 5))
s3 = set(range(3, 1000, 3))
s = s3 | s5

avec un bon gain d'efficacité.

Bruno.

Pierre Maurette

unread,
Nov 6, 2009, 8:54:50 AM11/6/09
to
PIGUET Bruno, le 06/11/2009 a ᅵcrit :
> Le Fri, 06 Nov 2009 10:55:38 +0100, Kaoron a ᅵcritᅵ:
>
>> Bonjour,
>>
>> Pouvez-vous m'enrichir d'une mᅵthode ᅵlᅵgante pour itᅵrer sur une liste
>> privᅵe de certains de ses ᅵlᅵments ?

>>
>> La solution que j'emploie actuellement est celle-ci :
>> >for e in list1 :
>> > if not e in list2 :
>> > <instructions>
>>
>
> Est-ce une situation oᅵ il est possible d'utiliser les ensembles
> ("sets") ?
>
> Dans un cas simple, j'ai remplacᅵ :

> l5 = range(5, 1000, 5)
> l3 = range(3, 1000, 3)
> l = l3
> for i in l5:
> if not i in l3:
> l.append(i)
>
> par :
> s5 = set(range(5, 1000, 5))
> s3 = set(range(3, 1000, 3))
> s = s3 | s5

Je pense que l'opᅵrateur, c'est - et non | (union).

on peut penser ᅵ

for e in set(list1) - set(list2):
etc.

Mais avec les set on change d'algo. Mᅵme sans parler de l'ordre. Dans
la question on ᅵliminait toutes les occurences d'un ᅵlᅵment s'il ᅵtait
prᅵsent dans list2, mais on traitait autant de fois les autres qu'ils
ᅵtaient dans list1. Avec les set, on ᅵlimine les doublons (et plus).

> avec un bon gain d'efficacitᅵ.

Sᅵr ?

--
Pierre Maurette


Alain Ketterlin

unread,
Nov 6, 2009, 10:04:06 AM11/6/09
to
Pierre Maurette <maurett...@wanadoo.fr> writes:

> PIGUET Bruno, le 06/11/2009 a écrit :

>> Est-ce une situation où il est possible d'utiliser les ensembles
>> ("sets") ?

[Je zappe les remarques pertinentes de Pierre, en particulier sur
l'ordre et les doublons.]

>> avec un bon gain d'efficacité.
>
> Sûr ?

Sûr. Au moins un facteur N/log(N) probablement, où N est la taille du
deuxième ensemble. Sauf cas très particulier.

-- Alain.

PIGUET Bruno

unread,
Nov 6, 2009, 12:07:31 PM11/6/09
to
Le Fri, 06 Nov 2009 14:54:50 +0100, Pierre Maurette a écrit :


> Mais avec les set on change d'algo.

C'est pour ça que j'ai commencé mon message par :
"Est-ce une situation où il est possible d'utiliser les ensembles
("sets") ?"

Le premier bout de code que j'ai recopié était une façon de faire une
liste unique en disant "si un nouvel élément n'est pas (déjà) dans la
liste, je l'ajoute (append)". Donc l'opérateur de set correspondant était
bien "|".
Mais cette transformation d'exclusion en union n'est pas forcément
celui que souhaitais l'OP. D'où mon introduction prudente.

> > avec un bon gain d'efficacité.
>
> Sûr ?

Le bon benchmarking est un art difficile. Sur mon cas, et ce que j'ai pu
en mesurer, oui.

Bruno.

Pierre Maurette

unread,
Nov 6, 2009, 3:15:42 PM11/6/09
to
PIGUET Bruno, le 06/11/2009 a ᅵcrit :
> Le Fri, 06 Nov 2009 14:54:50 +0100, Pierre Maurette a ᅵcritᅵ:

>
>
>> Mais avec les set on change d'algo.
>
> C'est pour ᅵa que j'ai commencᅵ mon message par :
> "Est-ce une situation oᅵ il est possible d'utiliser les ensembles
> ("sets") ?"
>
> Le premier bout de code que j'ai recopiᅵ ᅵtait une faᅵon de faire une
> liste unique en disant "si un nouvel ᅵlᅵment n'est pas (dᅵjᅵ) dans la
> liste, je l'ajoute (append)". Donc l'opᅵrateur de set correspondant ᅵtait
> bien "|".
> Mais cette transformation d'exclusion en union n'est pas forcᅵment
> celui que souhaitais l'OP. D'oᅵ mon introduction prudente.

Dᅵsolᅵ. Je ne pensais pas que vous ᅵtiez aussi ᅵloignᅵ que ᅵa du
problᅵme de l'OP, et comme souvent j'ai lu en diagonale et ce que je
*voulais* lire, ᅵ savoir:

l5 = range(5, 1000, 5)
l3 = range(3, 1000, 3)

l = [] #et non l = l3 !!!


for i in l5:
if not i in l3:
l.append(i)

ce qui fait ce que veut l'OP, aux doublons prᅵs bien entendu.

Ce que vous faisiez, c'est la liste des multiples - non nuls - de 3 et
de 5, en faisant attention ᅵ ne pas inclure deux fois les multiples
communs, donc les multiples de 15.
C'est effectivement complᅵtement un problᅵme d'ensemble. Le gain de
performance reste ᅵnorme mᅵme en faisant
s = sorted(list(s3 | s5))

Remarque: par rapport ᅵ la solution bourrin, on est - dans certaines
conditions de test - ~10 fois plus rapide en faisant:

l5 = range(5, 1000, 5)
l3 = range(3, 1000, 3)

l15 = range(15, 1000, 15)


l = l3
for i in l5:

if not i in l15:
l.append(i)

mais ᅵa reste au moins 5 fois plus lent qu'avec les ensembles, mᅵme en
convertissant le rᅵsultat en liste triᅵe.

>>> avec un bon gain d'efficacitᅵ.
>>
>> Sᅵr ?


>
> Le bon benchmarking est un art difficile. Sur mon cas, et ce que j'ai pu
> en mesurer, oui.

J'ai mesurᅵ ᅵgalement, quand le problᅵme est adaptᅵ aux ensembles, la
diffᅵrence est monstrueuse, effectivement. Il est d'ailleurs clair que
set(range()) est traitᅵ spᅵcifiquement, et non pas comme
set(listequelconque()).

--
Pierre Maurette


Kaoron

unread,
Nov 6, 2009, 7:45:29 PM11/6/09
to
Alain BARTHE wrote:
> Ca va surement en faire hurler plus d'un mais j'aime bien
> (et puis c'est vendredi) :
>
> for e in list1:
> if e in list2: continue
> <instructions-sans-approfondir-inutilement-l-indentation>
>
> J'adore faire des trucs comme �a dans les boucles :
> on peut mettre plein de tests en d�but de boucle, pour ignorer toute une
> s�rie de cas, sans approfondir inutilement...
>
> Ca �vite parfois de se retrouver avec le bloc d'instructions "utiles"
> perdu dans une 3eme, 4eme niveau d'indentation, ce qui n'est pas
> forc�ment plus lisible que quelques instructions continue bien
> identifi�es en d�but de boucle.


Les deux solutions que vous proposez me paraissent tr�s lisibles et
explicites, ce qui est en quelque sorte mon crit�re supr�me d'�l�gance.

Je vois par ailleurs que les deux ont �t� propos�es en r�ponse � une
proposition de changement de la syntaxe de for sur la ML python-dev :

http://mail.python.org/pipermail/python-dev/2008-May/079556.html
http://mail.python.org/pipermail/python-dev/2008-May/079567.html

C'est le genre d'enrichissement que j'�tais venu chercher, merci beaucoup :)

Alain BARTHE

unread,
Nov 7, 2009, 4:15:15 AM11/7/09
to Kaoron
Kaoron a �crit :

De rien :)

0 new messages