python - 使用两组不同的键创建字典

标签 python dictionary

好的,所以我有一本 super 英雄的字典,以他们的名字作为键,还有一本包含大量附加信息的字典:

heroes = {
    "Superman": {
        "weaknesses": ["kryptonite", "Martha"],
        "alter_ego": "Clark Kent",
        ...},
    "Batman": {
        "weaknesses": [],
        "alter_ego": "Bruce Wayne",
        ...},
    ...
   }

由于我可能计划闯入城市中的一些庄园,我想确认房主实际上不是英雄,或者至少有足够的信息以便我可以相应地准备。

这种数据结构,查找起来有点笨重

victim_name = "Clark Kent"

# Check if the victim is not the alterego of an hero
def check_victim_is_hero(victim, heroes):
    alter_egos = [hero["alter_ego"] for  hero in heroes.values()]
    return victim in alter_egos

# I can also get the name of the specific hero
def check_which_hero_is_victim(victim, heroes):
    for hero_name, hero in heroes.items():
        if hero["alter_ego"] == victim:
            return hero_name

我可以先获取英雄的名字,然后简单地调用原始字典上的 get,或者稍微更改 check_wich_hero_is_victim 以返回 hero[ “弱点”] 而不是 hero_name

然而,这两种解决方案都迫使我迭代字典,随着我收集的信息的增加,它变得越来越昂贵。

我想要的是有一个对象,我可以从中调用 get 从 super 英雄或 alterego 名称,成本为 O(1)。

类似于:

heroes_double_index = ...

heroes_double_index.get_from_hero_name("Superman")
>>> {"name": "Superman", "alter_ego": "Clark Kent", "weaknesses":...}

heroes_double_index.get_from_alterego("Clark Kent")
>>> {...} Same dictionary as above

我目前的想法是有一个类,其中包含我喜欢的每组键的两个字典:

class DoubleIndexDict:

    # Assuming we get the data as a list of records
    def __init__(self, data):
         self.dict_heroes = {hero["name"]: hero for hero in data}
         self.dict_alterego = {hero["alter_ego"]: hero for hero in data}

    def get_from_hero_name(self, name):
         return self.dict_heroes.get(name)

    def get_from_alter_ego(self, name):
         return self.dict_alterego.get(name)

但是这并不能完全满足我,最值得注意的是因为我可以在不影响查询完成方式的情况下更改每个字典中的值。

heroes_double_index.get_from_hero_name("Captain America")
>>> {"name": "Captain America", "alter_ego": "Steve Rogers"}


# Make the change
heroes_double_index.dict_heroes["Captain America"]["alter_ego"] = "Isaiah Bradley"

# The difference appears inside of the dictionary
heroes_double_index.get_from_hero_name("Captain America")
>>> {"name": "Captain America", "alter_ego": "Isaiah Bradley"}

# But I cannot use the new alterego for my search
heroes_double_index.get_from_alterego("Isaiah Bradley")
>>> None

是否有任何既定且更有效的方法来做我想在 python 中做的事情?

最佳答案

如果您只想能够在 O(1) 上同时更新 alter_ego 和 name(我认为这不是用于更多 key 的可扩展解决方案),那么您可以这样做:

class Heroes:
def __init__(self, data):
    self.id_by_hero = {}
    self.id_by_alter_ego = {}
    self.data = {}

    for i, h in enumerate(data):
        self.id_by_hero[h["name"]] = str(i)
        self.id_by_alter_ego[h["alter_ego"]] = str(i)
        self.data[str(i)] = HeroDict(self, h)

def __getitem__(self, key):
    id = self.id_by_hero.get(key) or self.id_by_alter_ego.get(key)
    return self.data[id] if id else None

def update_key(self, key, old, new):
    if key == "name":
        self.id_by_hero[new] = self.id_by_hero.pop(old)
    if key == "alter_ego":
        self.id_by_alter_ego[new] = self.id_by_alter_ego.pop(old)

class HeroDict(object):
def __init__(self, parent, init=None):
    self.parent = parent
    if init is not None:
        self.__dict__.update(init)

def __setitem__(self, key, value):
    old = self.__dict__[key]
    self.__dict__[key] = value
    self.parent.update_key(key, old, value)

def __repr__(self):
    r = self.__dict__.copy()
    del r['parent']
    return repr(r)

通过将真实数据保存在一个字典中,您不必在每次更改值或选择从何处获取它时都更新它们。然后,当您更新一个值时,它会调用 update_key 并只更新引用。 这样,您将获得:

heroes_double_index["Captain America"]
>>> {'name': 'Captain America', 'weaknesses': [], 'alter_ego': 'Steve Rogers'}

heroes_double_index["Captain America"]["alter_ego"] = "Isaiah Bradley"

heroes_double_index["Captain America"]
>>> {'name': 'Captain America', 'weaknesses': [], 'alter_ego': 'Isaiah Bradley'}

heroes_double_index["Isaiah Bradley"]
>>> {'name': 'Captain America', 'weaknesses': [], 'alter_ego': 'Isaiah Bradley'}

关于python - 使用两组不同的键创建字典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63412432/

相关文章:

python - 使用来自不同数据集的组均值填充一个数据集中的缺失值

python - 如何在 Python 中使用多处理对循环进行并行求和

python - 获得所需输出的替代方法 "Numpy Vectorized "

python - 为什么 python 需要 __init__.py 将目录视为包含包?

Python-删除字典对的比例/百分比

使用列表理解将字典扁平化为列表的 Pythonic 方法

python 通过 ssh 连接 mysql

javascript - 如何获得一个国家的交互式地理 map ?

python - 有效地就地过滤字典

Python,打印字典中每种可能组合的元素和的键