Понимание - удивительная особенность python, но это не всегда лучший случай. Вместо того, чтобы создавать кучу переменных и объединять их, было бы неплохо обрабатывать их по одному. Я уверен, что из этого кода можно выжать больше сока, но это должно обеспечить хороший баланс читаемости и вычислительной мощности. Я проверил вывод, чтобы убедиться, что он совпадает с выводом вашего кода.
dicTfAll = {
1: {'c1': ['aa', 'bb', 'cc']},
2: {'c1': ['dd', 'ee', 'ff']}
}
dicTf = {
1: {'c2': ['aax', 'bbx', 'cc']},
2: {'c2': ['ddy', 'eey', 'ff']},
3: {'c2': ['xx', '11']}
}
outputCompanies = {}
for d in [dicTfAll, dicTf]:
for idx, records in d.items():
for company, items in records.items():
if company not in outputCompanies.keys():
outputCompanies[company] = {}
for item in items:
outputCompanies[company][item] = idx
print(outputCompanies)
# {
# 'c2': {'11': 3, 'ddy': 2, 'eey': 2, 'cc': 1, 'xx': 3, 'ff': 2, 'bbx': 1, 'aax': 1},
# 'c1': {'aa': 1, 'bb': 1, 'cc': 1, 'dd': 2, 'ee': 2, 'ff': 2}
# }
Поскольку вы ищете более производительный код, вот сравнение времени выполнения с использованием %%timeit
в лаборатории jupyter.
# My version
2.99 µs ± 30 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
# Original Version
6.39 µs ± 25.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Я также попробовал немного более компактную версию кода, но это заняло больше времени для запуска.
%%timeit
outputCompanies = defaultdict(dict)
for d in [dicTfAll, dicTf]:
for idx, records in d.items():
for company, items in records.items():
outputCompanies[company].update({item: idx for item in items})
# 4.88 µs ± 22.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Еще один тест, который включает в себя понимание:
%%timeit
outputCompanies = {}
for d in [dicTfAll, dicTf]:
for idx, records in d.items():
for company, items in records.items():
if company not in outputCompanies.keys():
outputCompanies[company] = {}
outputCompanies[company].update({
item: idx for item in items
})
# 4.99 µs ± 23.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Что касается некоторых комментариев к вашему коду, dict.keys()
возвращает объект list
, поэтому нет необходимости вызывать list(dict.keys())
. Также нет необходимости создавать переменную allKeys
, так как вы можете вызывать dict.keys()
в своем понимании словаря. Компании жестко запрограммированы, что хорошо, если это единственный сценарий, но не лучший, если вы ожидаете, что набор данных будет расширяться со временем. Но если вы хотите жестко их кодировать, вы можете пропустить объявление переменной и просто набрать for company in ['c1','c2']:
. Затем вы можете сохранить еще несколько переменных, создав dicTfAllP
, равное первому пониманию, и затем обновив его вторым. Сложите все это вместе, и вы получите следующий код. Это более читабельно и немного легче следовать, но не намного более производительно.
%%timeit
dicTfAllP = {
item[0]:item[1]
for item
in dicTf.items()
if item[0] not in dicTfAll.keys()
}
dicTfAllP.update({
item[0]: dict(dicTfAll[item[0]], **item[1])
for item
in dicTf.items()
if item[0] in dicTfAll.keys()
})
outputCompanies = {}
for company in ['c1','c2']:
theKeys = [key for key in dicTfAllP.keys() if company in dicTfAllP[key]]
outputCompanies[company] = {
token:key
for key in theKeys
for token in dicTfAllP[key][company]
}
# 6.11 µs ± 58.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)