我正在使用此方法,但for循环跳过元素。经过调试后,我知道为什么会跳过它,所以我想知道是否有更好的方法或正确的方法。
这是我的代码:
class Birthday:
name = ''
date = ''
def __init__(self, name, date):
self.name = name
self.date = date
...
dt1 = datetime.datetime.utcfromtimestamp(1428916628.0) # Year: 2015
dt2 = datetime.datetime.utcfromtimestamp(1328916628.0) # Year: 2012
dt3 = datetime.datetime.utcfromtimestamp(1228916628.0) # Year: 2008
dt4 = datetime.datetime.utcfromtimestamp(1128916628.0) # Year: 2005
dt5 = datetime.datetime.utcfromtimestamp(1028916628.0) # Year: 2002
b1 = Birthday('John', dt1)
b2 = Birthday('Larry', dt2)
b3 = Birthday('David', dt3)
b4 = Birthday('Joe', dt4)
b5 = Birthday('Jerry', dt5)
# Elements are mixed on purpose
dt_list = [b3, b1, b5, b4, b2]
# Sort the order of elements by date
dt_list.sort(key=lambda y: y.date)
for x in dt_list:
dt_list.remove(x)
if len(dt_list) <= 3:
break
Expected: 2008, 2012, 2015
Result: 2005, 2012, 2015
我想把它添加到for循环的第一个换行符中:
x = dt_list[0]
但感觉不对。
答案 0 :(得分:3)
首先,改变你正在迭代的列表几乎不是一个好主意。特别是,这是您当前问题的来源。让我们来看一个类似的例子。
l = [1, 2, 3, 4]
for x in l:
l.remove(x)
print(l) # [2, 4]
对列表进行迭代将返回l[0]
,l[1]
,l[2]
...等等,直到它到达列表的末尾。特别是,这意味着如果索引更改,您可能会跳过某些元素。这就是这里发生的事情。
如果你想改变你的清单,你应该怎么做。
l = [1, 2, 3, 4, 5]
del l[:-3]
print(l) # [3, 4, 5]
尽管如此,变异数据并不比创建新列表更具时间效率。从列表中删除元素时,下一个元素需要向左移动,这是昂贵的。上面的操作是 O(n),其中 n 是列表的长度。
在这种情况下,创建新列表实际上更有效。
切片列表会返回一个新列表,并且 O(k)其中 k 是切片的大小。因此,恢复最后三个元素实际上是在恒定的时间内运行。
l = [1, 2, 3, 4, 5]
new_l = l[-3:]
print(new_l) # [3, 4, 5]
此外,由于list.__getitem__
函数是用C语言编写的,因此与for循环相比,它的速度非常快。
这是获得最后三个元素的最快方法。