我有以下问题:
我有一个列表:
temp= [950, 1000, 1100, 1200, 1400, 1450, 1500, 1600, 1650, 1700, 1900, 1950, 2000, 2100, 2200]
在此列表中,我要删除每个< 1200 and > 1950
值。
我尝试了以下操作:
for x in temp:
if x < 1200 or x > 1950:
temp.remove(x)
这给了我以下结果:
[1000, 1200, 1400, 1450, 1500, 1600, 1650, 1700, 1900, 1950, 2100]
但是我的目标输出如下:
[1200, 1400, 1450, 1500, 1600, 1650, 1700, 1900, 1950]
我找到了一种通过切片完成任务的方法:
new_temp = temp[temp.index(1200):temp.index(1950)+1]
这给了我想要的输出:
[1200, 1400, 1450, 1500, 1600, 1650, 1700, 1900, 1950]
但是我想了解为什么 attemp1 不起作用,并且也许有比 attemp2
更好的方法来完成我的任务有人可以帮忙吗?预先感谢。
答案 0 :(得分:2)
您的 attempt1 不起作用,因为您修改了循环的同一列表。这可能会导致各种奇怪的行为,例如跳过某些值。这是一个示例:
>>> lst = [1, 2]
>>> for val in lst:
... lst.remove(val)
...
>>> lst
[2] # wat?
请勿这样做:请勿修改循环显示的列表。
记录下来,这是最简单的正确方法(不一定是最快的方法):
result = [value for value in temp if 1200 <= value <= 1950]
还请注意,切片方法temp[temp.index(1200):temp.index(1950)+1]
仅在对列表进行排序的前提下有效。在这种假设下,我们可以比任何一种提出的方法都快得多。即我们可以进行二进制搜索+切片。但是,除非您处理数百万个值,否则复杂性可能不值得。
答案 1 :(得分:2)
我将创建一个用于识别有效值的函数:
def validated(value):
return 1200 <= value <= 1950
然后您可以在list comprehension中使用它:
>>> [value for value in temp if validated(value)]
[1200, 1400, 1450, 1500, 1600, 1650, 1700, 1900, 1950]
或者您可以使用filter
>>> list(filter(validated, temp))
[1200, 1400, 1450, 1500, 1600, 1650, 1700, 1900, 1950]
编辑:遇到麻烦的原因是因为您无法修改要迭代的内容。它不“知道”您已将地毯从地毯下面拉出。
另一种方法是复制列表,然后遍历列表。
temp2 = temp[:] # makes a copy
for x in temp2:
if x < 1200 or x > 1950:
temp.remove(x)
此外,remove
是线性搜索(很慢)。通常最好做过滤器。如果您确实需要修改temp
所引用的列表(而不仅仅是使temp
指向其他列表),则可以执行以下操作:
temp[:] = [value for value in temp if validated(value)]
[:]
是一个分片运算符,如果您为其指定了分片运算符,它将替换原始列表的全部内容(而不是为名称分配新列表)。
答案 2 :(得分:1)
@freakish答案是正确的,我只是想使其更清晰。
由于列表迭代而跳过值是此行为的主要问题
请参见下面的中循环中的python列表迭代可视化
迭代1
temp= [950, 1000, 1100, 1200, 1400, 1450, 1500, 1600, 1650, 1700, 1900, 1950, 2000, 2100, 2200]
currentIndex = 0
(值为 950 的项目)
删除索引为0的元素
进行第二次迭代
迭代2
温度看起来像这样
temp= [1000, 1100, 1200, 1400, 1450, 1500, 1600, 1650, 1700, 1900, 1950, 2000, 2100, 2200]
currentIndex = 1
(值为 1100 的项目)
删除索引为1的元素
进行第三次迭代
迭代3
温度看起来像这样
temp= [1000, 1200, 1400, 1450, 1500, 1600, 1650, 1700, 1900, 1950, 2000, 2100, 2200]
currentIndex = 2
(值为 1400 的项目)
1400 < 1200
,然后转到下一个元素。
我希望应该足够清楚地了解由于这种迭代而发生的事情。为了避免这种行为,请尝试使用其他方法列出exporessions或numpy数组。
答案 3 :(得分:0)
import numpy as np
temp= np.array([950, 1000, 1100, 1200, 1400, 1450, 1500, 1600, 1650, 1700, 1900, 1950, 2000, 2100, 2200])
temp[(temp>=1200) & (temp<=1950)]
输出:
array([1200, 1400, 1450, 1500, 1600, 1650, 1700, 1900, 1950])