2009-08-31 5 views
2

ContexteGénérer deux listes à la fois

L'algorithme d'analyse financière manipule. Il existe plusieurs listes de la même taille et elles sont filtrées dans d'autres listes pour analyse. Je fais le même filtrage sur différentes listes parallèles. Je pourrais le configurer de telle sorte que a1, b1, c2 se présente sous la forme d'un tuple dans une liste, mais les analyses doivent ensuite rayer les tuples dans l'autre sens (régression d'une liste par rapport à l'autre, bêta, etc.).

Ce que je veux faire

Je veux générer deux listes différentes en fonction d'une troisième liste:

>>> a = list(range(10)) 
>>> b = list(range(10,20)) 
>>> c = list(i & 1 for i in range(10)) 
>>> 
>>> aprime = [a1 for a1, c1 in zip(a,c) if c1 == 0] 
>>> bprime = [b1 for b1, c1 in zip(b,c) if c1 == 0] 
>>> aprime 
[0, 2, 4, 6, 8] 
>>> bprime 
[10, 12, 14, 16, 18] 

Il semble qu'il devrait y avoir une pythonique/programmation fonctionnelle/itertools façon de créer les deux listes et itérer sur les trois listes une seule fois. Quelque chose comme:

aprime, bprime = [a1, b1 for a1, b1, c1 in zip(a,b,c) if c1 == 0] 

Mais bien sûr cela génère une erreur de syntaxe.

La question

est-il un moyen pythonique?

Shootout Micro-optimisation

Le laid, mais pythonique-to-the-max bords d'une doublure sur le "juste utiliser une boucle for" solution et mon code d'origine dans le très populaire timeit match en cage:

>>> import timeit 
>>> timeit.timeit("z2(a,b,c)", "n=100;a = list(range(n)); b = list(range(10,10+n)); c = list(i & 1 for i in range(n));\ndef z2(a,b,c):\n\treturn zip(*[(a1,b1) for a1,b1,c1 in zip(a,b,c) if c1==0])\n") 
26.977873025761482 
>>> timeit.timeit("z2(a,b,c)", "n=100;a = list(range(n)); b = list(range(10,10+n)); c = list(i & 1 for i in range(n));\ndef z2(a,b,c):\n\taprime, bprime = [], [];\n\tfor a1, b1, c1 in zip(a, b, c):\n\t\tif c1 == 0:\n\t\t\taprime.append(a1); bprime.append(b1);\n\treturn aprime, bprime\n") 
32.232914169258947 
>>> timeit.timeit("z2(a,b,c)", "n=100;a = list(range(n)); b = list(range(10,10+n)); c = list(i & 1 for i in range(n));\ndef z2(a,b,c):\n\treturn [a1 for a1, c1 in zip(a,c) if c1 == 0], [b1 for b1, c1 in zip(b,c) if c1 == 0]\n") 
32.37302275847901 
+2

Pourquoi vous essayez de itérer sur les listes en parallèle? Quel est le problème global que vous cherchez à résoudre? C'est probablement plus simple que d'essayer d'itérer sur plusieurs listes parallèles. –

+0

L'algorithme manipule l'analyse financière. Il existe plusieurs listes de la même taille et elles sont filtrées dans d'autres listes pour analyse. C'est vraiment le cas que je fais le même filtrage sur différentes listes parallèles. Je pourrais le configurer de telle sorte que a1, b1, c2 se présente sous la forme d'un tuple dans une liste, mais les analyses doivent ensuite rayer les tuples dans l'autre sens (régression d'une liste par rapport à l'autre, bêta, etc.). – hughdbrown

+0

Je ne comprends pas quel est le problème avec le code que vous avez pour créer aprime et bprime. En quoi est-ce incorrect ou inadapté? –

Répondre

3

Cela pourrait gagner le prix code le plus laid, mais il fonctionne en une ligne:

aprime, bprime = zip(*[(a1,b1) for a1,b1,c1 in zip(a,b,c) if c1==0]) 
+0

@ kaizer.se: que signifie ce commentaire? – hughdbrown

+0

Peut-être que ce zip peut être utilisé pour décompresser si vous utilisez un astérisque? zip (* zip (a, b)) == a, b – ACoolie

+0

zip - unzip, on dirait que ça pourrait être un idiot de python mais à la fin je pense qu'il est rarement utilisé; une boucle for est plus claire. En passant, vous pouvez utiliser une expression de générateur au lieu de la liste de compréhension (je ne suis pas sûr que cela importe ici), et puis il y a itertools.izip si les listes sont très longues. – u0b34a0f6ae

0

il n'y a pas moyen de créer plusieurs listes à la fois avec la liste compréhensions - si vous voulez seulement itérer une fois que vous allez avoir besoin de le faire d'une autre manière - possible avec une boucle .

Vous pourrait utiliser une liste de compréhension pour créer une liste de tuples, avec le premier élément appartenant à une liste, la seconde à l'autre. Mais si vous les voulez en tant que listes séparées, vous devrez utiliser une autre opération pour le diviser, de toute façon.

4

Il suffit d'utiliser une boucle for:

aprime = [] 
bprime = [] 
for a1, b1, c1 in zip(a, b, c): 
    if c1 == 0: 
     aprime.append(a1) 
     bprime.append(b1)