遍历元组列表并删除它们

时间:2020-06-01 21:44:10

标签: 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 = 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')]

我是一个初学者,任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:3)

请不要修改要遍历的列表的(长度)。而是使用例如临时列表:

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

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

    if day > 31 or month > 12:
        continue
    out.append(date)

dates = out

print(dates)

continue语句跳回到循环的第一行,因此不需要的日期将被跳过。

更好的替代日期

评论程序的“日期检查”功能:可能很难根据自己的规则来确定哪些日期可以接受,哪些日期不能接受。例如,以2月29日为例,它仅每四年有效一次。

您可以做的是使用datetime库尝试将字符串解析为datetime对象,如果解析失败,您就知道日期是非法的。

import datetime as dt 

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

def filter_bad_dates(dates):
    out = []
    for date in dates:

        try:
            dt.datetime.strptime('-'.join(date), '%d-%m-%Y')
        except ValueError:
            continue

        out.append(date)

    return out


dates = filter_bad_dates(dates)
print(dates)

try - except模式也称为“鸭子输入”:

如果它看起来像日期,并且像正确的日期一样被解析,则可能是正确的日期。

答案 1 :(得分:1)

您可以通过以下列表理解轻松实现这一目标:

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)

输出:

[('12', '10', '1987'), ('13', '09', '2010')]

答案 2 :(得分:0)

我喜欢@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)

输出

> python3 test.py
[('12', '10', '1987'), ('13', '09', '2010')]
>

就@ 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)