Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

écriture pythonesque

12 réponses
Avatar
Olivier Ravard
Bonjour à tous,

Voici un petit problème :

J'ai une liste de la forme :
a = [[(1,11),(2,22),(3,33)], [(4,44),(5,55)], ...]

et je veux obtenir la liste suivante :
[(1,11),(2,22),(3,33),(4,44),(5,55), ...]

Bien sûr, les entiers 1,2,3, ..., 11, 22, 33, ...
sont des nombres choisis ici arbitrairement.
Je souhaite faire cette opération de manière "pythonesque"
et efficace (les listes peuvent être longues...).

Pour faire cette opération :

1. utilisation de "extend"
b = []
[b.extend(r) for r in a]
il me semble que l'utilisation de "extend" est relativement lente.

2. Utilisation de numpy
c = numpy.ravel(a)
b = [(c[i],c[i+1]) for i in range(len(c))[::2]]
Je ne suis pas sûr que cette solution soit plus rapide que la précédente.
De plus la fonction ravel ne fonctionne que si le nombre d'éléments
de chaque liste de niveau 1 soit de même taille. Dans mon exemple, ça ne
fonctionne que si a = [[(1,11),(2,22),(3,33)], [(4,44),(5,55),(6,66)], ...]

Avez-vous d'autres suggestions ?


O.R.

10 réponses

1 2
Avatar
Olivier Ravard
resultat = [r for b in a for r in b]
Avatar
Bruno Desthuilliers
Olivier Ravard a écrit :
resultat = [r for b in a for r in b]



Hors contexte, c'est totalement incompréhensible - et donc fort peu
pythonesque.
Avatar
Olivier Ravard
Bruno Desthuilliers a écrit :
Olivier Ravard a écrit :
resultat = [r for b in a for r in b]



Hors contexte, c'est totalement incompréhensible - et donc fort peu
pythonesque.



a = [[(1,11),(2,22),(3,33)], [(4,44),(5,55)]]
resultat = [r for b in a for r in b]
print resultat

--> [(1, 11), (2, 22), (3, 33), (4, 44), (5, 55)]

C'est mieux ?
Avatar
Alain Ketterlin
Olivier Ravard writes:

Voici un petit problème :

J'ai une liste de la forme :
a = [[(1,11),(2,22),(3,33)], [(4,44),(5,55)], ...]

et je veux obtenir la liste suivante :
[(1,11),(2,22),(3,33),(4,44),(5,55), ...]



reduce(lambda x,y : x+y, a)

-- Alain.
Avatar
Boris Borcic
Olivier Ravard wrote:

1. utilisation de "extend"


...
il me semble que l'utilisation de "extend" est relativement lente.



Sur quelle base ?


2. Utilisation de numpy


...
Je ne suis pas sûr que cette solution soit plus rapide que la précé dente.


...
Avez-vous d'autres suggestions ?



Sur le principe de ne pas s'occuper de la performance à moins de la mes urer :

http://docs.python.org/library/timeit.html

Sur le problème de base, vérifier qu'une liste est bien nécessaire, ou si
itertools.chain (<2.6) ou itertools.chain.from_iterable (2.6) peut faire l'affaire.

http://docs.python.org/library/itertools.html#itertools.itertools.chain.f rom_iterable

hth, bb
Avatar
Michel Claveau - NoSpam SVP ; merci
Bonsoir !

Tu te définis une petite fonction qui aplatit des listes imbriquées
(quelque soit la profondeur d'imbrication), puis tu l'utilises au
besoin.

Exemple :

def aplati(l):
for item in l:
if isinstance( item, types.ListType):
for iii in aplati( item):
yield iii
else:
yield item

print list(aplati(l))


@+
--
Michel Claveau
Avatar
Christophe
Michel Claveau - NoSpam SVP ; merci a écrit :
Bonsoir !

Tu te définis une petite fonction qui aplatit des listes imbriquées
(quelque soit la profondeur d'imbrication), puis tu l'utilises au besoin.

Exemple :

def aplati(l):
for item in l:
if isinstance( item, types.ListType):
for iii in aplati( item):
yield iii
else:
yield item

print list(aplati(l))


@+



Tiens, c'est utile d'utiliser types.ListType au lieu de list ? Moi
j'aurais mis isinstance( item, list ). Y aurait-il un problème avec
cette notation ?
Avatar
Olivier Ravard
Boris Borcic wrote:
Olivier Ravard wrote:

1. utilisation de "extend"


...
il me semble que l'utilisation de "extend" est relativement lente.



Sur quelle base ?



Il est vrai que ce n'est qu'une impression conditionnée par une réflexion qui n'est pas
objective. Cette impression est le résultat de mon expérience où, dans certains cas
(réception TCP d'un flux haut débit - de l'ordre de 800 Mb/s par exemple), la création de
chaines puis l'utilisation de "join" est beaucoup plus rapide que l'utilisation de
"append". Ceci dit, ce sont des chaînes et non des listes.
Je n'ai pas fait de mesures de vitesse.


2. Utilisation de numpy


...
Je ne suis pas sûr que cette solution soit plus rapide que la précédente.


...
Avez-vous d'autres suggestions ?



Sur le principe de ne pas s'occuper de la performance à moins de la
mesurer :

http://docs.python.org/library/timeit.html

Sur le problème de base, vérifier qu'une liste est bien nécessaire, ou
si itertools.chain (<2.6) ou itertools.chain.from_iterable (2.6) peut
faire l'affaire.

http://docs.python.org/library/itertools.html#itertools.itertools.chain.from_iterable


hth, bb



Avatar
Michel Claveau - NoSpam SVP ; merci
Bonjour !

J'ai pris l'habitude d'utiliser types car ce module contient des types
génériques très pratiques. Comme, par exemple, types.StringTypes, qui
permet de tester à la fois les chaînes String et Unicode.
Du coup, j'utilise toujours la même notation, ce qui m'évite de me poser
des questions.

@+
--
Michel Claveau
Avatar
Michel Claveau - NoSpam SVP ; merci
Bonjour !

reduce(



reduce est excellent, pour ce genre de chose (tant qu'il n'y a pas
plusieurs niveaux, et donc pas de récursion). Attention, avec Python 3,
cette fonction va migrer dans functools.

@+
--
Michel Claveau
1 2