通过理解创建空列表

Creating empty lists with comprehension

我想获得有关此代码的一些帮助:

from datetime import datetime

flights = {
'09:35' : 'FREEPORT',
 '09:55' : 'WEST END',
 '10:45' : 'TREASURE CAY',
 '11:45' : 'ROCK SOUND',
 '12:00' : 'TREASURE CAY',
 '17:00' : 'FREEPORT',
 '17:55' : 'ROCK SOUND',
 '19:00' : 'WEST END' }

def convert_to_ampm(time24: str) -> str:
    return datetime.strptime(time24, '%H:%M').strftime('%I:%M %p')

flights_copy = {}


for k, v in flights.items():
    if v not in flights_copy:
        flights_copy[v] = []
    flights_copy[v].append(k)


for k, v in flights_copy.items():
    time = []
    for item in v:
        time.append(convert_to_ampm((item)))
    print(k.title(), ':',time)

有没有办法让这段代码以理解的方式编写:

for k, v in flights.items():
    if v not in flights_copy:
        flights_copy[v] = []
    flights_copy[v].append(k)

我目前正在学习Python,我的知识不是很丰富,也很抱歉我的英语水平很差。谢谢!


最简单的方法是使用 defaultdict IMO:

from collections import defaultdict

flights_copy = defaultdict(list)
for k, v in flights.items():
    flights_copy[v].append(k)

可以通过理解来做到这一点,但更困难——直接理解会覆盖值而不是附加值:

>>> {v: k for k, v in flights.items()}
{'FREEPORT': '17:00', 'WEST END': '19:00', 'TREASURE CAY': '12:00', 'ROCK SOUND': '17:55'}

所以你需要一个嵌套推导,一个为每个键构建值列表的内部列表推导:

>>> {v: [k for k, val in flights.items() if v == val] for v in flights.values()}
{'FREEPORT': ['09:35', '17:00'], 'WEST END': ['09:55', '19:00'], 'TREASURE CAY': ['10:45', '12:00'], 'ROCK SOUND': ['11:45', '17:55']}

请注意,这样做效率较低,因为现在您要多次遍历原始字典(从 O(n) 到 O(n^2))。

作为一个单一的理解,你至少可以这样做:

from itertools import groupby
from operator import itemgetter

flights_copy = {
    v: [i[0] for i in d]
    for v, d in groupby(sorted(flights.items(), key=itemgetter(1)), itemgetter(1))
}

所以如果航班是:{1: 20, 2: 20, 3: 10, 4: 15} 那么上面的代码会产生:{10: [3], 15: [4], 20: [1, 2]}

但是,您的初始代码是可读的并且工作正常。您可以通过以下方式对其进行一些改进:

from collections import defaultdict

flights_copy = defaultdict(list)
for k, v in flights.items():
    flights_copy[v].append(k)

不是通过字典理解,而是通过使用 defaultdict,在我看来这是非常可读的:

>>> from collections import defaultdict
>>> flights_copy_2 = defaultdict(list)
>>> for flight_time, flight_dest in flights.items():
...     flights_copy_2[flight_dest].append(flight_time)
...
>>> print(dict(flights_copy_2))
{'FREEPORT': ['09:35', '17:00'], 'WEST END': ['09:55', '19:00'], 'TREASURE CAY': ['10:45', '12:00'], 'ROCK SOUND': ['11:45', '17:55']}