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

2024-04-26 00:02:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我有这样的json文件:

{
    "K1": {
        "p": [
            "A"
        ], 
        "s": [
            "B", 
            "C"
        ]
    }, 
    "K2": {
        "p": [
            "A", 
            "F"
        ], 
        "s": [
            "G", 
            "H",
            "J"
        ]
    }
}

我可以很容易地读入这些数据:

import json

with open('json_lists_to_sets.json') as fi:
    data = json.load(fi)

然后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']}}

但是,为了进一步分析,最好使用sets而不是lists。在读入数据之后,我当然可以将lists转换成sets

for vi in data.values():
    vi['p'] = set(vi['p'])
    vi['s'] = set(vi['s'])

这给了我想要的输出:

print data['K2']

收益率

{u'p': {u'A', u'F'}, u's': {u'G', u'H', u'J'}}

我的问题是,当我在json.load命令中读取数据时,是否可以直接将这些lists转换为sets,例如“将找到的所有列表转换为集合”。这样的事情存在吗?你知道吗


Tags: 文件数据importjsondatawithsetsload
2条回答

下面是使用dict comprehension实现这一点的一行表达式:

>>> {key: {k: set(v) for k, v in nested_dict.items()} for key, nested_dict in data.items()}
{'K2': {'s': {'H', 'G', 'J'}, 'p': {'A', 'F'}}, 'K1': {'s': {'B', 'C'}, 'p': {'A'}}}

但是,如果您想使用loop实现它,下面是一个示例:

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']}}
for key, nested_dict in data.items():
    data[key] = {k: set(v) for k, v in nested_dict.items()}

# Value of 'data': {'K2': {'s': {'H', 'G', 'J'}, 'p': {'A', 'F'}}, 'K1': {'s': {'B', 'C'}, 'p': {'A'}}}

尽管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

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

>>> 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'])}}

但是要考虑到,包含其他字典的列表不能处理,因为字典是不可散列的。你知道吗

如果希望找到嵌套在其他列表中的列表,则必须切换到使用frozenset()而不是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

相关问题 更多 >