2010-02-02 7 views
3

Je suis à la recherche d'une méthode «agréable» pour traiter une liste où certains éléments doivent être développés en plusieurs éléments (une seule fois, pas d'expansion sur les résultats).Expansion d'éléments dans une liste

manière itérative standard serait de le faire:

i=0 
while i < len(l): 
    if needs_expanding(l[i]): 
     new_is = expand(l[i]) 
     l[i:i] = new_is 
     i += len(new_is) 
    else: 
     i += 1 

qui est assez laid. Je pourrais réécrire le contenu dans une nouvelle liste avec:

nl = [] 
for x in l: 
    if needs_expanding(x): 
     nl += expand(x) 
    else: 
     nl.append(x) 

Mais ils semblent tous les deux trop longs. Ou je pourrais simplement faire 2 passes et aplatir la liste plus tard:

flatten(expand(x) if needs_expanding(x) else x for x in l) 
# or 
def try_expanding(x).... 
flatten(try_expanding(x) for x in l) 

mais cela ne se sent pas « droit » non plus.

Existe-t-il d'autres façons claires de le faire?

+0

Je pense que la 2ème version est assez claire. – kennytm

+0

@KennyTM: J'utiliserais normalement le dernier. Je voulais juste voir ce que les autres pourraient trouver/serait à l'aise d'utiliser/voir dans le code de la vie réelle. – viraptor

Répondre

2

Si vous n'avez pas besoin d'un accès aléatoire dans la liste que vous générez, vous pouvez également utiliser un générateur écrire.

def iter_new_list(old_list):  
    for x in old_list: 
     if needs_expanding(x): 
      for y in expand(x): 
       yield y 
     else: 
      yield x 

new_list = list(iter_new_list(old_list)) 

Ceci est fonctionnellement équivalent à votre deuxième exemple, mais il pourrait être plus lisible dans votre situation réelle.

En outre, les normes de codage Python interdisent l'utilisation de L comme nom de variable, car elle est presque impossible à distinguer de la lettre numérique.

+0

re. minuscule-L-pylint ne cesse de me rappeler;) Je l'ai utilisé seulement pour sauver la frappe dans un exemple trivial ... – viraptor

2

Le dernier est probablement votre plus pythonique, mais vous pouvez essayer une boucle implicite (ou AP3, générateur) avec carte:

flatten(map(lambda x: expand(x) if needs_expanding(x) else x, l)) 
flatten(map(try_expanding, l)) 
3

Vos deux dernières réponses sont ce que je ferais. Cependant, je ne connais pas flatten(), mais si vous avez une telle fonction, cela semble idéal. Vous pouvez également utiliser le haut-sum():

sum(expand(x) if needs_expanding(x) else [x] for x in l, []) 
sum(needs_expanding(x) and expand(x) or [x] for x in l, []) 
+0

Ok - somme est assez cool - ne pense pas à celui-là. Aplatir est juste une fonction personnalisée pour aplatir la liste - pas en python (malheureusement). – viraptor

+1

Malheureusement 'sum()' a des performances quadratiques pour les listes –

Questions connexes