2011-06-07 14 views
5

Me gustaría hacer un ciclo de una lista y eliminar el elemento si cumple con el requisito. Al mismo tiempo, transformaría el elemento eliminado y agregaría el resultado de la transformación a otra lista.¿Cuál debería ser la manera pitónica de implementar la siguiente lógica?

En este momento, he implementado por encima de la lógica siguiente código:

delete_set = set([]) 

for item in my_list: 
    if meet_requirement(item): 
     another_list.append = transform(item) 
     delete_set.add(item) 

my_list = filter(lambda x:x not in delete_set, my_list) 

El código no es tan sencillo, ¿existe una mejor manera de implementar la lógica?

+1

Mientras que iba a escribir de otra manera (forma de gato Plus Plus probablemente), no veo nada malo en su enfoque. –

Respuesta

6

Puede hacerlo con solo comprensión.

delete_set = set(I for I in my_list if meet_requirement(I)) 
another_list.extend(transform(I) for I in delete_set) 
# or extend(transform(I) for I in my_list if I in delete_set), if duplicates/order matter 
my_list = [I for I in my_list if I not in delete_set] 
+0

Tenga en cuenta que esto cambia el orden de los elementos en 'another_list'. –

+0

¿Hora de copia superficial? '[:]' –

1

Se podría hacer esto para evitar el conjunto:

def part(items, others): 
    for item in items: 
     if meet_requirement(item): 
      others.append(item) 
     else: 
      yield item 

mylist[:] = part(mylist, another_list) 
0
>>> another_list = [] 
>>> new_list = [] 
>>> 
>>> for item in my_list: 
...  (another_list if meet_requirement(item) else new_list).append(item) 
... 
>>> another_list = map(transform, another_list) 
>>> my_list = new_list 
3

No estoy seguro sobre Pythonic, pero si pitón tenía una función partition similar a Haskell (o se podría escribir un simple uno mismo), el código no necesitaría iterar sobre la lista original dos veces (como en la solución de Cat Plus).

me gustaría utilizar algo como lo siguiente:

new_my_list, deleted_list = partition(my_list, meet_requirement) 
deleted_list = [transform(e) for e in deleted_list] 
+0

+1 para la idea de partición –

1

se podía hacer esto

for i in reversed(xrange(len(my_list))): 
    if meet_requirement(my_list[i]): 
     another_list.append(transform(my_list.pop(i))) 

entonces es posible o no posible que desee invertir another_list (o puede utilizar un deque y appendleft)

0
zipped = zip(*[(item, transform(item)) for item in my_list \ 
               if meet_requirement(item)]) 
another_list = zipped[1] 
my_list = [item for item in my_list if item not in zipped[0]] 
0

Necesitaba algo similar el otro d Ay:

def partition(pred, iterable): 
    result = ([], []) 
    for each in iterable: 
     result[pred(each)].append(each) 
    return result 

xs = some_list  
ys, xs[:] = partition(meet_some_requirement, xs) 
ys = map(do_some_transformation, ys) 

O esta variación de una sola pasada:

def partition_and_transform(pred, iterable, *transform): 
    result = ([], []) 
    for each in iterable: 
     v = pred(each) 
     result[v].append(transform[v](each)) 
    return result 

ys, xs[:] = partition_and_transform(meet_some_reqirement, xs, do_some_transformation, lambda x:x) 
Cuestiones relacionadas