Как поддерживать порядок совпадения между двумя python словарями при выполнении арифметических c операций - PullRequest
0 голосов
/ 29 января 2020

У меня есть два оригинальных объявленных словаря:

members = OrderedDict({
    "member1" : ["PCP2", "PCP3"],
    "member2" : ["PCP1", "PCP2"],
    "member3" : ["PCP3"],
    "member4" : ["PCP1"],
    "member5" : ["PCP4", "PCP5"],
    "member6" : ["PCP1", "PCP5"],
    "member7" : ["PCP2", "PCP3", "PCP4"],
    "member8" : ["PCP3", "PCP5"],
    "member9" : ["PCP1", "PCP4", "PCP5"],
    "member10" : ["PCP2", "PCP4"],
    "member11" : ["PCP2"],
    "member12" : ["PCP3"],
    "member13" : ["PCP4", "PCP5"]
    })
providers = OrderedDict({
    "PCP1" : 3,
    "PCP2" : 4,
    "PCP3" : 2,
    "PCP4" : 3,
    "PCP5" : 4,
})

значения providers - это количество слотов, открытых для приема участников. Затем я создаю новый словарь общей суммы, запрошенной members для каждого провайдера.

PCPcounts = {}
for m in members.values():
    for v in m:
        if v in PCPcounts:
            PCPcounts[v] += 1
        else:
            PCPcounts[v] = 1
PCPcounts

Если я запускаю свою ячейку ноутбука точно так же, я получаю ее вывод в нужном порядке:

{'PCP1': 4, 'PCP2': 5, 'PCP3': 5, 'PCP4': 5, 'PCP5': 5}

Но если я использую print(PCPcounts), я получаю:

{'PCP2': 5, 'PCP3': 5, 'PCP1': 4, 'PCP4': 5, 'PCP5': 5}

Хорошо, хорошо, я пытаюсь сделать арифметическую c различную операцию между двумя:

differences = dict()
    for (k,v), (k2,v2) in zip(PCPcounts.items(), providers.items()):
        differences[k] = v - v2

print(differences)
{'PCP2': 2, 'PCP3': 1, 'PCP1': 2, 'PCP4': 2, 'PCP5': 1}

Это не правильно. Например, PCP1: 2 должно быть, PCP1: 1. Он принимает разницу между распечатанным порядком PCPcounts и providers. Я пытался использовать OrderedDict() при объявлении учетных записей PCP, и это также возвращает их в неправильном порядке. Как мне поддерживать соответствующие порядки ключей? Я не мог найти такой вопрос в другом посте. Спасибо

Ответы [ 2 ]

2 голосов
/ 29 января 2020

Вы можете использовать collections.Counter вместо collections.OrderedDict:

from collections import Counter

members = {
    "member1" : ["PCP2", "PCP3"],
    "member2" : ["PCP1", "PCP2"],
    "member3" : ["PCP3"],
    "member4" : ["PCP1"],
    "member5" : ["PCP4", "PCP5"],
    "member6" : ["PCP1", "PCP5"],
    "member7" : ["PCP2", "PCP3", "PCP4"],
    "member8" : ["PCP3", "PCP5"],
    "member9" : ["PCP1", "PCP4", "PCP5"],
    "member10" : ["PCP2", "PCP4"],
    "member11" : ["PCP2"],
    "member12" : ["PCP3"],
    "member13" : ["PCP4", "PCP5"]}
providers = Counter({
    "PCP1" : 3,
    "PCP2" : 4,
    "PCP3" : 2,
    "PCP4" : 3,
    "PCP5" : 4,
})

PCPcounts = Counter()

for m in members.values():
    PCPcounts.update(m)

differences = PCPcounts - providers

Различия отпечатков:

Counter({'PCP3': 3, 'PCP4': 2, 'PCP2': 1, 'PCP1': 1, 'PCP5': 1})

Это можно еще улучшить с помощью itertools.chain

from itertools import chain
PCPcounts = Counter(chain(*members.values()))

Вместо для l oop.

1 голос
/ 29 января 2020

Как насчет того, чтобы вместо архивирования использовать что-то вроде:

differences = dict()
for k in PCPcounts:
    differences[k] = PCPcounts[k] - providers[k]

Я думаю, что почтовый индекс делает его слишком сложным, поскольку у вас уже есть общие ключи

...