我有一个列表,其中一些项目将被移动到一个单独的列表中(通过比较器功能)。这些元素是纯粹的元素。问题是如何迭代这样的列表。
当迭代最简单的方法for element in mylist
时,我不知道元素的索引。列表没有.iteritems()
方法,这在这里很有用。所以我尝试使用for index in range(len(mylist)):
,[1]似乎过于复杂,因为python和[2]不满足我,因为range(len())
在开头计算一次,如果我删除一个迭代期间列表中的元素,我将得到IndexError: list index out of range
。
最后,我的问题是 - 如何迭代python列表,能够从列表中删除元素(使用比较器函数并将它们放在另一个列表中)?
答案 0 :(得分:2)
您可以使用枚举功能并制作列表的临时副本:
for i, value in enumerate(old_list[:]):
# i == index
# value == dictionary
# you can safely remove from old_list because we are iterating over copy
答案 1 :(得分:1)
我不想触及原始列表并像@ Martol1ni一样,但是一种方法来实现并且不受元素删除的影响将是向后迭代:
for i in reversed(range(len()):
# do the filtering...
这将仅影响您已经测试/删除的元素的索引
答案 2 :(得分:1)
Haven没试过这个但是......我会给它一个快速的镜头:
new_list = [old.pop(i) for i, x in reversed(list(enumerate(old))) if comparator(x)]
答案 3 :(得分:1)
尝试使用filter命令,如果不需要,也可以使用它覆盖原始列表。
def cmp(i): #Comparator function returning a boolean for a given item
...
# mylist is the initial list
mylist = filter(cmp, mylist)
mylist现在是合适物品的发电机。如果您需要多次使用,可以使用list(mylist)
。
答案 4 :(得分:1)
与从旧项目中删除项目相比,创建新列表确实不是什么大问题。类似地,迭代两次是一个非常小的性能命中,可能被其他因素淹没。除非您有充分的理由不做其他事情,在分析代码的支持下,我建议迭代两次并构建两个新列表:
from itertools import ifilter, ifilterfalse
l1 = list(ifilter(condition, l))
l2 = list(ifilterfalse(condition, l))
如果需要,您可以将其中一个新列表的内容切片 - 分配到原始列表中:
l[:] = l1
如果您完全确定需要1-pass解决方案,而且您绝对确定要修改原始列表而不是创建副本,则以下内容可避免pop
的二次性能命中从列表中间ping:
j = 0
l2 = []
for i in range(len(l)):
if condition(l[i]):
l[j] = l[i]
j += 1
else:
l2.append(l[i])
del l[j:]
我们将列表中的每个元素直接移动到其最终位置,而不会浪费不需要移位的时移元素。如果需要,我们可以使用for item in l
,它可能会更快一点,但是当算法涉及修改我们正在迭代的事物时,我更喜欢显式索引。
答案 5 :(得分:0)
你可以做到这一点,虽然可能只有一行。
new_list1 = [x for x in old_list if your_comparator(x)]
new_list2 = [x for x in old_list if x not in new_list1]