如何在加载json文件时将所有列表转换为集合

Cle*_*leb 2 python json

我有json文件,如下所示:

{
    "K1": {
        "p": [
            "A"
        ], 
        "s": [
            "B", 
            "C"
        ]
    }, 
    "K2": {
        "p": [
            "A", 
            "F"
        ], 
        "s": [
            "G", 
            "H",
            "J"
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)

我可以轻松阅读这些数据:

import json

with open('json_lists_to_sets.json') as fi:
    data = json.load(fi)
Run Code Online (Sandbox Code Playgroud)

然后data看起来如下:

{u'K2': {u'p': [u'A', u'F'], u's': [u'G', u'H', u'J']}, u'K1': {u'p': [u'A'], u's': [u'B', u'C']}}
Run Code Online (Sandbox Code Playgroud)

然而,对于我的进一步分析,最好使用sets而不是lists.我可以在读完数据后转换listssets:

for vi in data.values():
    vi['p'] = set(vi['p'])
    vi['s'] = set(vi['s'])
Run Code Online (Sandbox Code Playgroud)

这给了我想要的输出:

print data['K2']
Run Code Online (Sandbox Code Playgroud)

产量

{u'p': {u'A', u'F'}, u's': {u'G', u'H', u'J'}}
Run Code Online (Sandbox Code Playgroud)

我的问题是lists,sets当我读入json.load命令中的数据时,是否可以将这些转换为直接,因此类似于"将所有列表转换为集合".这样的事情存在吗?

Mar*_*ers 5

虽然json库提供了许多钩子来改变解码,但是没有挂钩来加载JSON数组.

您将不得不以后递归更新解码结果:

def to_sets(o):
    if isinstance(o, list):
        return {to_sets(v) for v in o}
    elif isinstance(o, dict):
        return {k: to_sets(v) for k, v in o.items()}
    return o
Run Code Online (Sandbox Code Playgroud)

这将处理任何嵌套字典深度的列表:

>>> to_sets(data)
{u'K2': {u'p': set([u'A', u'F']), u's': set([u'H', u'J', u'G'])}, u'K1': {u'p': set([u'A']), u's': set([u'C', u'B'])}}
Run Code Online (Sandbox Code Playgroud)

但是请注意,由于字典不可清除,因此无法处理包含其他字典的列表.

如果你希望找到嵌套在其他列表中的列表,你必须切换到使用a frozenset()而不是a set()来嵌套那些:

def to_sets(o):
    if isinstance(o, list):
        return frozenset(to_sets(v) for v in o)
    elif isinstance(o, dict):
        return {k: to_sets(v) for k, v in o.items()}
    return o
Run Code Online (Sandbox Code Playgroud)