检查字典中的键是否还作为值存在,如果存在,是否将它们合并?

时间:2019-09-26 01:26:49

标签: python dictionary

我正在尝试使用Python词典从Excel电子表格中创建分类结构。每个实体都有几个子实体,我想将其表示为嵌套的Python字典。

我的电子表格如下:

Entity              Includes
Account             Customer Account
Account             Corporate Account
Account             Account Balance
Account Balance     Exposure

依此类推。

我将文件加载到DataFrame中,然后通过Pandas的groupby-split-apply创建字典:

df = pd.read_excel('taxonomy_file.xlsx')

groupby = dict(df.groupby('Entity')['Includes'].apply(list))

我得到的字典如下:

{'Account': ['Customer Account',
             'Corporate Account',
             'Account Balance'],
 'Account Balance': ['Exposure']}

我想要的结果是写一些东西来检测“账户余额”既是键又是值,并将“值”的“账户余额”转换为既是值又是键的“曝光”:

{'Account': ['Customer Account',
             'Corporate Account',
             {'Account Balance': 'Exposure'}]

最终,我不需要处理大量的术语,但是我更希望不要手动执行。我已经尝试执行以下操作,只是为了测试是否可以在字典的各个部分中同时检测到键和值:

for k, v in groupby.items():
    if k in v:
        print(k)

但是没有运气,因为它只是在搜索每个键是否在该键的值列表中。我主要是在寻找有关如何解决该问题的任何指针或想法,或者我是否认为自己错了。

1 个答案:

答案 0 :(得分:1)

我假设您的文件是树结构的转换(但是它可以是任何有向图)。第一个想法是区分引用和根:根是永远都不是值的键,而引用是同时也是值的键:

all_values = set(x for xs in d.values() for x in xs)
refs = all_values & set(d.keys())

我们还需要一个在引用中搜索关键字并返回新字典的函数,如果找到该关键字:

def resolve_ref(key):
    if key in refs:
        return {key: [resolve_ref(x) for x in d[key]]}
    else:
        return key

此函数显然是递归的,因为我们需要解析ref,ref的ref...。最后,值中没有ref。

最后一部分是创建仅具有非引用键的字典,并解析值中的所有引用:

{k: [resolve_ref(x) for x in vs] for k, vs in d.items() if k not in refs}

让我们将这些块放在一起,并尝试一个更复杂的示例:

def consolidate(d):
    all_values = set(x for xs in d.values() for x in xs)
    refs = all_values & set(d.keys())

    def resolve_ref(key):
        if key in refs:
            return {key: [resolve_ref(x) for x in d[key]]}
        else:
            return key

    return {k: [resolve_ref(x) for x in vs] for k, vs in d.items() if k not in refs}

示例:

d = {'Account': ['Customer Account',
             'Corporate Account',
             'Account Balance'],
    'Account Balance': ['Exposure'],
    'Exposure': ['Foo', 'Bar']} 

print(consolidate(d))
# {'Account': ['Customer Account', 'Corporate Account', {'Account Balance': [{'Exposure': ['Foo', 'Bar']}]}]}

注意:循环将被删除,因为如果循环有根,那么它也将是be值,因此是ref而不是根。

d = {'Foo': ['Bar'],
    'Bar': ['Baz'],
    'Baz': ['Foo']}
print(consolidate(d))
# {}