首页 > 解决方案 > 组合字典,将匹配键与整数而不是字符串相加

问题描述

我正在编写一系列脚本,这些脚本将来自多个服务器的字典组合在一起用于我运行的游戏,因此我可以看到每个人在它们之间的表现。我想将所有字典合并在一起以获得一个“总计”。问题是字典是字符串、整数None和嵌套字典的组合。

这是一个例子。(对不起它很大)

{
  "3ec3557031b5474576456459e1cb3266ab0": {
    "PvP": {
      "kills": 9,
      "losses": 8
    },
    "friendlyCollisionHits": {},
    "friendlyCollisionKills": {},
    "friendlyHits": {},
    "friendlyKills": {},
    "id": 82,
    "kills": {
      "Buildings": {
        "Other": 0,
        "Static": 0,
        "total": 0
      },
      "Ground Units": {
        "AAA": 10,
        "APCs": 22,
        "Arty/MLRS": 0,
        "EWR": 0,
        "Forts": 0,
        "IFVs": 6,
        "Infantry": 11,
        "Other": 0,
        "SAM": 2,
        "Tanks": 8,
        "Unarmored": 6,
        "total": 65
      },
      "Helicopters": {
        "Attack": 1,
        "Other": 0,
        "Utility": 1,
        "total": 2
      },
      "Planes": {
        "Attack": 4,
        "Bombers": 0,
        "Fighters": 44,
        "Other": 0,
        "Support": 0,
        "Transports": 1,
        "UAVs": 0,
        "total": 49
      },
      "Ships": {
        "Other": 0,
        "Subs": 0,
        "Unarmed": 5,
        "Warships": 1,
        "total": 6
      }
    },
    "losses": {
      "crash": 36,
      "eject": 9,
      "pilotDeath": 24
    },
    "names": {
      1: "Mallachar",
      2: "ClanTag-Mallachar"
    },
    "times": {
      "A-10C": {
        "inAir": 14467.051,
        "total": 20852.44
      },
      "AV8BNA": {
        "inAir": 4871.472,
        "total": 7678.675
      },
      "F-15C": {
        "inAir": 20537.472,
        "total": 25509.876
      },
      "F-5E-3": {
        "inAir": 12416.944,
        "total": 19611.379
      },
      "FA-18C_hornet": {
        "inAir": 45838.898,
        "total": 59293.893
      }
    },
    "weapons": {
      "AGM-122": {
        "hit": 0,
        "kills": 0,
        "numHits": 0,
        "shot": 2
      },
      "AGM-65D": {
        "hit": 0,
        "kills": 3,
        "numHits": 3,
        "shot": 4
      },
      "AGM-65E": {
        "hit": 0,
        "kills": 2,
        "numHits": 2,
        "shot": 4
      },
      "AIM-120B": {
        "hit": 0,
        "kills": 4,
        "numHits": 5,
        "shot": 19
      },
      "AIM-120C": {
        "hit": 0,
        "kills": 8,
        "numHits": 9,
        "shot": 41
      },
      "AIM-7M": {
        "hit": 0,
        "kills": 8,
        "numHits": 10,
        "shot": 28
      },
      "AIM-9M": {
        "hit": 0,
        "kills": 15,
        "numHits": 22,
        "shot": 31
      },
      "AIM-9P5": {
        "hit": 0,
        "kills": 5,
        "numHits": 7,
        "shot": 8
      },
      "AIM-9X": {
        "hit": 0,
        "kills": 1,
        "numHits": 2,
        "shot": 2
      },
      "CBU-52B": {
        "hit": 0,
        "kills": 0,
        "numHits": 0,
        "shot": 8
      },
      "CBU-97/CBU-105 SFW": {
        "hit": 0,
        "kills": 21,
        "numHits": 30,
        "shot": 22
      },
      "CBU-99": {
        "hit": 0,
        "kills": 0,
        "numHits": 0,
        "shot": 4
      },
      "FFAR Mk5 HEAT": {
        "hit": 0,
        "kills": 0,
        "numHits": 2,
        "shot": 38
      },
      "GAU-8": {
        "hit": 0,
        "kills": 0,
        "numHits": 2,
        "shot": 8
      },
      "GBU-12": {
        "hit": 0,
        "kills": 1,
        "numHits": 1,
        "shot": 10
      },
      "HYDRA-70 MK5": {
        "hit": 0,
        "kills": 10,
        "numHits": 21,
        "shot": 376
      },
      "HYDRA-70 MK61": {
        "hit": 0,
        "kills": 0,
        "numHits": 2,
        "shot": 16
      },
      "M-39": {
        "hit": 0,
        "kills": 2,
        "numHits": 35,
        "shot": 8
      },
      "M-61": {
        "hit": 0,
        "kills": 1,
        "numHits": 1080,
        "shot": 69
      },
      "Mk-82": {
        "hit": 0,
        "kills": 6,
        "numHits": 20,
        "shot": 41
      },
      "Mk-83": {
        "hit": 0,
        "kills": 12,
        "numHits": 19,
        "shot": 26
      },
      "Zuni-127": {
        "hit": 0,
        "kills": 10,
        "numHits": 40,
        "shot": 68
      },
      "guns": {
        "hit": 36,
        "kills": 13,
        "numHits": 373,
        "shot": 5115
      }
    }
  }
}

它也变得有点复杂。['Names'] 可以是多个东西。根ID是实际播放器的唯一ID,一个播放器可以多次更改。它很复杂,因为出于某种原因,它们的关键是整数,而不是字符串......所以这也有点奇怪。

无论如何,我只是想弄清楚如何将这些文件中的 3 个尽可能地组合在一起。

我研究过使用 Counts,但显然一旦有嵌套的 dicts 和字符串,它就会释放出来。

标签: pythondictionary

解决方案


您可以尝试递归策略,假设任何给定键的所有字典中的类型都相同:

import copy

def combine_dicts(first, other):
    first = copy.deepcopy(first)

    for k, v in other.items():
        if k not in first:
            first[k] = v
        else:
            if type(v) == dict:
                first[k] = combine_dicts(first[k], v)
            elif type(v) == int:
                first[k] += v
    return first

对于字符串值,您需要更具体地说明您想要什么行为。级联?鉴于您提供的数据,这似乎不正确。


推荐阅读