Iro*_*ney 1 python for-loop list python-3.x
我还在学习python的基础知识,我花了一段时间阅读有关如何从for循环中删除python中列表中的项目的方法.我读过的所有内容都表明了这样做的复杂方法,他们说你在迭代它时不能从列表中删除项目.但是......这似乎有效:
class Object():
def __init__(self):
self.y = 0
object_list = [Object(), Object(), Object()]
for thing in object_list:
thing.y += 1
if thing.y > 10:
object_list.remove(thing)
Run Code Online (Sandbox Code Playgroud)
当其他人说它不是并且编写复杂的解决方法时,为什么这会起作用?是因为你不允许在Python 2中使用它,但可以在Python 3中执行吗?
这是正确的方法吗?它会像我想要的那样工作还是容易出错?如果我计划删除项目,是否建议以相反的顺序迭代列表?
很抱歉,如果之前已经回答过这个问题,但是很难知道哪些资源引用了什么,因为他们只是在标签中说"python"(至少,我一直在阅读的那些,也许那是因为我读过的所有资源)是python 2?)
谢谢!
编辑:
对不起,有几个复制和粘贴错误...我已修复它们......
编辑:
我一直在观看Raymond Hettinger的另一个视频......他提到了一种从字典中删除项目的方法,同时使用dict.keys()进行迭代.就像是:
d = {'text': 'moreText', 'other': 'otherText', 'blah': 'moreBlah'}
for k in d.keys():
if k.startswith('o'):
del d[k]
Run Code Online (Sandbox Code Playgroud)
显然使用键可以在迭代时删除项目.列表是否有等价物?如果有,我可以在列表上向后迭代并安全地删除项目
这里有些例子
def example1(lst):
for item in lst:
if item < 4:
lst.remove(item)
return lst
def example2(lst):
for item in lst[:]:
if item < 4:
lst.remove(item)
return lst
def example3(lst):
i = 0
while i < len(lst):
if lst[i] < 4:
lst.pop(i)
else:
i += 1
return lst
def example4(lst):
return [item for item in lst if not item < 4]
def example5(lst):
for item in reversed(lst):
if item < 4:
lst.remove(item)
return lst
def example6(lst):
for i, item in reversed(list(enumerate(lst))):
if item < 4:
lst.pop(i)
return lst
def example7(lst):
size = len(lst) - 1
for i, item in enumerate(reversed(lst)):
if item < 4:
lst.pop(size - i)
return lst
def example8(lst):
return list(filter(lambda item: not item < 4, lst))
import itertools
def example9(lst):
return list(itertools.filterfalse(lambda item: item < 4, lst))
# Output
>>> lst = [1, 1, 2, 3, 2, 3, 4, 5, 6, 6]
>>> example1(lst[:])
[1, 3, 3, 4, 5, 6, 6]
>>> example2(lst[:])
[4, 5, 6, 6]
>>> example3(lst[:])
[4, 5, 6, 6]
>>> example4(lst[:])
[4, 5, 6, 6]
>>> example5(lst[:])
[4, 5, 6, 6]
>>> example6(lst[:])
[4, 5, 6, 6]
>>> example7(lst[:])
[4, 5, 6, 6]
>>> example8(lst[:])
[4, 5, 6, 6]
>>> example9(lst[:])
[4, 5, 6, 6]
Run Code Online (Sandbox Code Playgroud)
示例1 此示例涉及遍历列表并从中删除值.这个问题是你在浏览时修改列表,所以你的列表在迭代期间会发生变化,因此会跳过一些元素.
示例2 这里我们迭代列表的浅表副本而不是列表本身.这个问题是,如果你有一个大的列表,这样做可能会很昂贵.
示例3
以下是使用pop代替的示例remove,问题remove是它从列表中删除它找到的值的第一个实例.除非你有相同的对象,否则这通常没有问题.(见例10)
示例4 而不是在此修改列表,而是使用列表推导创建新列表,仅允许指定值.
示例5
这是反向迭代列表的示例,不同之处在于我们使用内置reversed函数来应用for循环而不是使用计数器的while循环.
示例6
使用相似的示例pop.
示例7
使用更好的示例,pop因为我们不必回滚到列表以使用该reversed函数.
示例8 使用内置过滤器方法删除指定值的示例.
示例9
使用filerfalse来自的方法的类似示例itertools
class Example(object):
ID = 0
def __init__(self, x):
self._x = x
self._id = str(Example.ID)
Example.ID += 1
def __eq__(self, other):
return self._x == other._x
def __repr__(self):
return 'Example({})'.format(self._id)
def example10():
lst = [Example(5), Example(5)]
print(lst)
lst.remove(lst[1])
return lst
#Output
>>> example10()
[Example(0), Example(1)]
[Example(1)]
Run Code Online (Sandbox Code Playgroud)
示例10
这里我们创建两个具有相同值的Example对象,并且通过相等方法它们是相等的.该ID变量是在那里帮助我们区分两者.现在我们已经指定我们要从列表中删除第二个对象,但是因为两者都相等,所以实际上删除了第一个项目.
时间 这些都是非常艰难的时期,根据您的设备可能略有不同.虽然这些确定哪一个更快,但是这已经测试了10,000个项目的列表,所以如果你没有任何接近那个,那么任何选择都很好.
import timeit
import random
# Code from above is here
def test(func_name):
global test_lst
test_lst = lst[:]
return timeit.timeit("{}(test_lst)".format(func_name),
setup="from __main__ import {}, test_lst".format(func_name), number = 1)
if __name__ == '__main__':
NUM_TRIALS = 1000
lst = list(range(10000))
random.shuffle(lst) # Don't have to but makes it a bit interesting
test_list = lst[:]
for func in ('example2', 'example3', 'example4', 'example5',
'example6', 'example7', 'example8', 'example9'):
trials = []
for _ in range(NUM_TRIALS):
trials.append(test(func))
print(func, sum(trials) / len(trials) * 10000)
#Output
example2 8.487979147454494
example3 20.407155912623292
example4 5.4595031069025035
example5 7.945100572479213
example6 14.43537688078149
example7 9.088818018676008
example8 14.898256300967116
example9 13.865010859443247
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
281 次 |
| 最近记录: |