Я пытаюсь использовать понимание python 3.x для создания вложенной структуры словаря. Мой синтаксис понимания работает, но он очень медленный, особенно с большим набором данных. Я также создал желаемую структуру данных, используя циклы, и она работает намного быстрее, но я хотел бы знать, есть ли способ улучшить это понимание, чтобы сделать его более эффективным и потенциально работать так же быстро или быстрее, чем мой l oop code.
Мои входные данные представляют собой список словарей, каждый словарь излагает особенности радиолюбительского контакта (запись в журнале). Вот случайное подмножество моих данных (ограничено 20 записями, и ненужные ключи в словаре удалены, чтобы сделать это более понятным)
[{'BAND': '20M',
'CALL': 'AA9GL',
'COUNTRY': 'UNITED STATES OF AMERICA',
'QSO_DATE': '20170528',
'TIME_ON': '132100'},
{'BAND': '20M',
'CALL': 'KE4BFI',
'COUNTRY': 'UNITED STATES OF AMERICA',
'QSO_DATE': '20150704',
'TIME_ON': '034600'},
{'BAND': '20M',
'CALL': 'W8OTR',
'COUNTRY': 'UNITED STATES OF AMERICA',
'QSO_DATE': '20190119',
'TIME_ON': '194645'},
{'BAND': '10M',
'CALL': 'FY5FY',
'COUNTRY': 'FRENCH GUIANA',
'QSO_DATE': '20150328',
'TIME_ON': '161953'},
{'BAND': '17M',
'CALL': 'KD5FOY',
'COUNTRY': 'UNITED STATES OF AMERICA',
'QSO_DATE': '20190121',
'TIME_ON': '145630'},
{'BAND': '10M',
'CALL': 'K5GQ',
'COUNTRY': 'UNITED STATES OF AMERICA',
'QSO_DATE': '20150110',
'TIME_ON': '195326'},
{'BAND': '10M',
'CALL': 'CR5L',
'COUNTRY': 'PORTUGAL',
'QSO_DATE': '20151025',
'TIME_ON': '182351'},
{'BAND': '20M',
'CALL': 'AD4TR',
'COUNTRY': 'UNITED STATES OF AMERICA',
'QSO_DATE': '20170325',
'TIME_ON': '144606'},
{'BAND': '40M',
'CALL': 'EA8FJ',
'COUNTRY': 'CANARY ISLANDS',
'QSO_DATE': '20170618',
'TIME_ON': '020300'},
{'BAND': '10M',
'CALL': 'PY2DPM',
'COUNTRY': 'BRAZIL',
'QSO_DATE': '20150104',
'TIME_ON': '205900'},
{'BAND': '17M',
'CALL': 'MM0HVU',
'COUNTRY': 'SCOTLAND',
'QSO_DATE': '20170416',
'TIME_ON': '130200'},
{'BAND': '10M',
'CALL': 'LW3DG',
'COUNTRY': 'ARGENTINA',
'QSO_DATE': '20161029',
'TIME_ON': '210629'},
{'BAND': '10M',
'CALL': 'LW3DG',
'COUNTRY': 'ARGENTINA',
'QSO_DATE': '20151025',
'TIME_ON': '210714'},
{'BAND': '20M',
'CALL': 'EI7HDB',
'COUNTRY': 'IRELAND',
'QSO_DATE': '20170423',
'TIME_ON': '184000'},
{'BAND': '20M',
'CALL': 'KM0NAS',
'COUNTRY': 'UNITED STATES OF AMERICA',
'QSO_DATE': '20180102',
'TIME_ON': '142151'},
{'BAND': '10M',
'CALL': 'PY2TKB',
'COUNTRY': 'BRAZIL',
'QSO_DATE': '20150328',
'TIME_ON': '223535'},
{'BAND': '40M',
'CALL': 'EB1DJ',
'COUNTRY': 'SPAIN',
'QSO_DATE': '20170326',
'TIME_ON': '232430'},
{'BAND': '40M',
'CALL': 'LU6PCK',
'COUNTRY': 'ARGENTINA',
'QSO_DATE': '20150615',
'TIME_ON': '000200'},
{'BAND': '17M',
'CALL': 'G3RKF',
'COUNTRY': 'ENGLAND',
'QSO_DATE': '20190121',
'TIME_ON': '144315'},
{'BAND': '20M',
'CALL': 'UA1ZKI',
'COUNTRY': 'EUROPEAN RUSSIA',
'QSO_DATE': '20170508',
'TIME_ON': '141400'}]
Я хочу создать словарь, где каждый ключ является полосой (10M, 20M и т. Д. c), а значением будет словарь, в котором в качестве значений будут указаны страны, с которыми контактировали в этом диапазоне, и число контактов для каждой страны в этом диапазоне. Вот как выглядит мой вывод:
{'10M': {'ARGENTINA': 2,
'BRAZIL': 2,
'FRENCH GUIANA': 1,
'PORTUGAL': 1,
'UNITED STATES OF AMERICA': 1},
'17M': {'ENGLAND': 1, 'SCOTLAND': 1, 'UNITED STATES OF AMERICA': 1},
'20M': {'EUROPEAN RUSSIA': 1, 'IRELAND': 1, 'UNITED STATES OF AMERICA': 5},
'40M': {'ARGENTINA': 1, 'CANARY ISLANDS': 1, 'SPAIN': 1}}
Это понимание, которое я придумал для создания вывода. Он работает, и с ограниченным набором данных, показанным здесь, он работает быстро, но с входным списком из нескольких тысяч записей, он занимает довольно много времени.
worked_dxcc_by_band = {
z["BAND"]: {
x["COUNTRY"]: len([y["COUNTRY"]
for y in log_entries
if y["COUNTRY"] == x["COUNTRY"] and y["BAND"] == z["BAND"]])
for x in log_entries
if x["BAND"] == z["BAND"]
}
for z in log_entries
}
Поскольку это тройной Это означает, что все три цикла проходят через весь список log_entries, поэтому я предполагаю, что он очень медленный.
Есть ли более эффективный способ выполнить sh с помощью понимания? Я хорошо использую свой l oop для обработки данных, но я пытаюсь улучшить свои навыки в области понимания, поэтому я подумал, что это будет хорошим упражнением!
Это то, что я делаю без использования понимания: я есть функция analyize_log_entry, которую я вызываю при загрузке каждой записи журнала из файла.
from collections import Counter
worked_dxcc_by_band = {}
def analyze_log_entry(entry):
if "BAND" in entry:
if "COUNTRY" in entry:
if entry["BAND"] in worked_dxcc_by_band:
worked_dxcc_by_band[entry["BAND"]][entry["COUNTRY"]] += 1
else:
worked_dxcc_by_band[entry["BAND"]] = Counter()
worked_dxcc_by_band[entry["BAND"]][entry["COUNTRY"]] = 1
Это само по себе может быть не столь эффективным, но мой полный код содержит много аналогичных блоков в функции analysis_log_entry, которые создают несколько словари. Поскольку я только один раз просматриваю все свои данные и строю словари там, где это уместно, это, вероятно, гораздо более эффективно, чем использование понимания, которое по сути состоит из нескольких циклов. Как я уже сказал, это больше упражнение, чтобы научиться выполнять sh одну и ту же задачу разными методами.