Python 循环遍历元组列表并删除它们

Python 循环遍历元组列表并删除它们,python,loops,tuples,Python,Loops,Tuples,我很难理解为什么我的循环没有从dd/mm/yyyy格式的日期元组列表中删除无效日期。以下是我到目前为止的情况: dates = [('12','10','1987'),('13','09','2010'), ('34','02','2002'), ('02','15','2005'),('37','10','2016'),('39','11','2001')] print(dates) for date in dates : day = int(date[0]) month =

我很难理解为什么我的循环没有从dd/mm/yyyy格式的日期元组列表中删除无效日期。以下是我到目前为止的情况:

dates = [('12','10','1987'),('13','09','2010'), ('34','02','2002'), ('02','15','2005'),('37','10','2016'),('39','11','2001')]
print(dates)

for date in dates :
    day = int(date[0])
    month = int(date[1])
    year = int(date[2])

    if day > 31 :
        dates.remove(date)


    if month > 12 :
        dates.remove(date)



print(dates)
结果如下:

[('12', '10', '1987'), ('13', '09', '2010'), ('34', '02', '2002'), ('02', '15', '2005'), ('37', '10', '2016'), ('39', '11', '2001')]

[('12', '10', '1987'), ('13', '09', '2010'), ('02', '15', '2005'), ('39', '11', '2001')]
我是一个完全的初学者,任何帮助都将不胜感激。

永远不要修改正在循环的列表(长度)。例如,使用临时列表:

dates=[('12','10','1987'),('13','09','2010'),('34','02','2002'),('02','15','2005'),('37','10','2016'),('39','11','2001')]
打印(日期)
out=[]
对于日期中的日期:
日期=整数(日期[0])
月份=整数(日期[1])
年份=整数(日期[2])
如果日期>31或月份>12:
持续
out.append(日期)
日期=过期
打印(日期)
continue
语句跳回循环的第一行,因此将跳过不需要的日期

更好的约会选择 评论该程序的“日期检查”功能:根据您自己的规则,可能很难确定哪些日期是可接受的,哪些是不可接受的。例如,2月29日,它只在每第四年生效一次。 相反,您可以使用
datetime
库尝试将字符串解析为datetime对象,如果解析失败,您就知道日期是非法的

将日期时间导入为dt
日期=[('12','10','1987'),('13','09','2010'),('34','02','2002'),('02','15','2005'),('37','10','2016'),('39','11','2001')]
def过滤器错误日期(日期):
out=[]
对于日期中的日期:
尝试:
dt.datetime.strtime('-'.join(日期),“%d-%m-%Y”)
除值错误外:
持续
out.append(日期)
返回
日期=筛选错误日期(日期)
打印(日期)
这种
try-except
模式也称为“Duck-Typing”:

如果它看起来像一个日期,并且被解析为一个正确的日期,那么它可能是一个正确的日期


通过以下列表,您可以轻松完成此任务:

dates = [('12','10','1987'),('13','09','2010'), ('34','02','2002'), ('02','15','2005'),('37','10','2016'),('39','11','2001')]
dates = [date for date in dates if int(date[1]) < 12 and int(date[0]) < 31]
print(dates)

我喜欢@AnnZen的理解方法(+1),尽管我倾向于在浪费时间和空间的情况下更具象征性:

dates = [ \
    ('12', '10', '1987'), \
    ('13', '09', '2010'), \
    ('34', '02', '2002'), \
    ('02', '15', '2005'), \
    ('37', '10', '2016'), \
    ('39', '11', '2001'), \
]

dates = [date for (day, month, _), date in zip(dates, dates) if day < '31' and month < '12']

print(dates)
至于@np8的“永远不要修改你正在循环的列表”,这是很好的建议。不过,同样,我可能会浪费一些空间预先制作副本以简化代码:

for date in list(dates):  # iterate over a copy
    day, month, _ = date

    if int(day) > 31 or int(month) > 12:
        dates.remove(date)

尽管最终,@np8通过
datetime
进行过滤似乎是最可靠的解决方案。(+1)

因此,我应该为正确的日期创建一个新列表,而不是在循环浏览时编辑现有列表。那么我的代码中发生了什么?当我删除一个元组时,是不是让它错过了迭代?再次感谢,你说得对。解决这个问题的一种方法是创建空列表并开始填充,而不是修改原始列表。是的,事情就是这样:您在遍历列表时从列表中删除了一些内容,这导致它甚至无法检查某些日期。您还可以通过在每次迭代时打印日期来查看原始代码的行为。为什么使用反斜杠?@AnnZen,反斜杠是Python中的行延续字符。根据我使用的PEP-8语法检查器,不使用它们是一个“错误的继续”错误。我不喜欢它们,特别是因为你不能用评论来跟随它们,但偶尔我也会用它们来提醒自己这种语言有多时髦。如果你这么说,不使用它们是一个“糟糕的延续”错误,你是说当我们只在一行中列出时,还是当我们在多行中列出时,没有反斜杠?@AnnZen,后者,多行。当然,将列表放在一行违背了PEP-8不合理地缩短79个字符的行长度限制样式建议。因此需要分成多行并使用连续字符。请注意,括号/方括号内不需要连续反斜杠,您可以安全地删除答案中的反斜杠。有时您可能会遇到一个“技巧”,即使用括号和隐式字符串连接:
s=(“句子开头”“结尾”)
> python3 test.py
[('12', '10', '1987'), ('13', '09', '2010')]
>
for date in list(dates):  # iterate over a copy
    day, month, _ = date

    if int(day) > 31 or int(month) > 12:
        dates.remove(date)