What should be the pythonic way to implement following logic?
I would like to loop a list and remove element if it meets the requirement. At the same time, I would transform the removed element and add the transformation result to another list.
Right now, I have implemented ab开发者_StackOverflow社区ove logic by following code:
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)
The code is not so straight-forward, is there a better way to implement the logic?
You could do this with comprehensions only.
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]
Not sure about pythonic, but if python had a partition
function similar to haskell (or you could write a simple one yourself), the code wouldn't need to iterate over the original list twice (as in Cat Plus' solution).
I would use something like the following:
new_my_list, deleted_list = partition(my_list, meet_requirement)
deleted_list = [transform(e) for e in deleted_list]
you could do this
for i in reversed(xrange(len(my_list))):
if meet_requirement(my_list[i]):
another_list.append(transform(my_list.pop(i)))
then you might or might not want to reverse another_list
(or you can use a deque
and appendleft
)
You could do this to avoid the set:
def part(items, others):
for item in items:
if meet_requirement(item):
others.append(item)
else:
yield item
mylist[:] = part(mylist, another_list)
>>> 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
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]]
I needed something similar the other day:
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)
Or this one-pass variation:
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)
精彩评论