如何遍历列表,删除元素?

时间:2019-03-25 14:44:07

标签: python

我想遍历列表中包含的字典,并删除早于特定日期的ARRIVAL DATE TIME项。 我已经审查了类似的先前问题(similar questionanother oneand another one),但鉴于数据结构的复杂性,我正在努力应用建议的解决方案。 到目前为止,这是我尝试过的。解决方案似乎我需要遍历数据结构的重复项,但是我该怎么做呢?

from datetime import datetime
ferry = [ {
      "NAME":"SNAV Atlair",
      "LAST CALLING PORT":"Casamicciola Terme",
      "CALLING PORTS HISTORY":{
         "MONDAY":[
              {
               "PORT":"Casamicciola Terme",
               "ARRIVAL DATE TIME":"2019-03-19 20:12:10"
            },
            {
               "PORT":"Casamicciola Terme",
               "ARRIVAL DATE TIME":"2019-03-19 16:12:10"
            }
         ] ,
          "TUESDAY":[
            {
               "PORT":"Casamicciola Terme",
               "ARRIVAL DATE TIME":"2019-03-19 20:12:10"
            }
         ],
         "WEDNESDAY":[

         ],
         "THURSDAY":[

         ],
         "FRIDAY":[

         ],
         "SATURDAY":[

         ],
         "SUNDAY":[

         ]
      }
   }]

datetime_last_position = '2019-03-23 12:50:00'
for entry in list(ferry):
  for i in range(len(entry['CALLING PORTS HISTORY']['MONDAY'])):
    if datetime.strptime(entry['CALLING PORTS HISTORY']['MONDAY'][i]['ARRIVAL DATE TIME'], '%Y-%m-%d %H:%M:%S').date() < datetime.strptime(datetime_last_position, '%Y-%m-%d %H:%M:%S').date():
      del entry['CALLING PORTS HISTORY']['MONDAY'][i]

4 个答案:

答案 0 :(得分:2)

从列表中删除元素的另一种方法(如果您以相反的顺序进行迭代(如another answer中指出的那样,则可以这样做)是仅创建一个仅包含要保留在其中的元素的新列表每种情况:

from datetime import datetime

ferry = [...]
datetime_last_position = '2019-03-23 12:50:00'
ref_date = datetime.strptime(datetime_last_position, '%Y-%m-%d %H:%M:%S').date()
for entry in list(ferry):
  callings = entry['CALLING PORTS HISTORY']
  for day in callings:
    callings[day][:] = [call for call in callings[day]
                        if datetime.strptime(call['ARRIVAL DATE TIME'], '%Y-%m-%d %H:%M:%S').date() >= ref_date]

print(ferry)
# [{'NAME': 'SNAV Atlair', 'LAST CALLING PORT': 'Casamicciola Terme', 'CALLING PORTS HISTORY': {'MONDAY': [], 'TUESDAY': [], 'WEDNESDAY': [], 'THURSDAY': [], 'FRIDAY': [], 'SATURDAY': [], 'SUNDAY': []}}]

此外,请注意,您当前正在编辑ferry中的对象,因此list(ferry)中的for entry in list(ferry):实际上并没有做任何事情。如果要使用保留旧对象的已修改对象创建新列表,则需要制作每个对象的副本,或者在应用修改之前只使用copy.deepcopy

答案 1 :(得分:1)

如果您以相反的顺序遍历项目,则可以安全地删除它们:

for i in range(len(entry['CALLING PORTS HISTORY']['MONDAY'])-1, -1, -1):
    if datetime.strptime(entry['CALLING PORTS HISTORY']['MONDAY'][i]['ARRIVAL DATE TIME'], '%Y-%m-%d %H:%M:%S').date() < datetime.strptime(datetime_last_position, '%Y-%m-%d %H:%M:%S').date():
        del entry['CALLING PORTS HISTORY']['MONDAY'][i]

当然,您可能不想在每个工作日都重写它,所以这样可能会更好:

for weekday in entry["CALLING PORTS HISTORY"]:
    for i in range(len(entry['CALLING PORTS HISTORY'][weekday])-1, -1, -1):
        if datetime.strptime(entry['CALLING PORTS HISTORY'][weekday][i]['ARRIVAL DATE TIME'], '%Y-%m-%d %H:%M:%S').date() < datetime.strptime(datetime_last_position, '%Y-%m-%d %H:%M:%S').date():
            del entry['CALLING PORTS HISTORY'][weekday][i]

答案 2 :(得分:1)

如果应删除条目的元素,则可以“跳过”该元素,然后将其替换为下一个可接受的元素,然后将该列表缩短为“未跳过”元素的数量:

datetime_last_position = '2019-03-23 12:50:00'
for entry in list(ferry):
    ptr = 0  # index where algorithm will store element
    for value in entry['CALLING PORTS HISTORY']['MONDAY']:
        if datetime.strptime(
            entry['CALLING PORTS HISTORY']['MONDAY'][i]['ARRIVAL DATE TIME'],
            '%Y-%m-%d %H:%M:%S'
        ).date() < datetime.strptime(datetime_last_position, '%Y-%m-%d %H:%M:%S').date():
            pass  # say, skip element
        else:
            # write then increment pointer
            entry['CALLING PORTS HISTORY']['MONDAY'][ptr] = value
            ptr += 1
    # shorten a list
    entry['CALLING PORTS HISTORY']['MONDAY'] = entry['CALLING PORTS HISTORY']['MONDAY'][:ptr]

ferry
Out:
[{'CALLING PORTS HISTORY': {'FRIDAY': [],
   'MONDAY': [],
   'SATURDAY': [],
   'SUNDAY': [],
   'THURSDAY': [],
   'TUESDAY': [{'ARRIVAL DATE TIME': '2019-03-19 20:12:10',
     'PORT': 'Casamicciola Terme'}],
   'WEDNESDAY': []},
  'LAST CALLING PORT': 'Casamicciola Terme',
  'NAME': 'SNAV Atlair'}]

它具有O(n)的复杂性,并且没有意外行为。

答案 3 :(得分:0)

根据我对您的问题的了解,您希望删除每个工作日列表中ARRIVAL DATE TIME早于给定日期的元素。

由于您提供的日期是字符串,因此我们需要创建一个函数以将它们转换为datetime对象:

strToDate = lambda date_string: datetime.strptime(date_string, '%Y-%m-%d %H:%M:%S')

从那里开始,循环遍历各种元素(假设您的结构是恒定的),然后根据需要为每个工作日创建一个新列表,这很简单。您可以就地修改字典,但不能修改列表,这就是为什么我在下面使用列表理解来创建新列表的原因:

for item in ferry:
    for weekday in item["CALLING PORTS HISTORY"]:
        item["CALLING PORTS HISTORY"][weekday] = [subitem 
                                                  for subitem in item["CALLING PORTS HISTORY"][weekday] 
                                                  if strToDate(subitem["ARRIVAL DATE TIME"]) >= date]

这将保留日期早于date的那些对象,同时消除那些日期不早于python的对象,从而得到您想要的结构!