You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何以更Pythonic的方式将np.array应用于嵌套字典的最内层列表?

嵌套字典内层列表转NumPy数组的Pythonic实现

我有如下结构的嵌套字典:

scores = {'default': {'MSE': [[1.0,2.0], [3.0,4.0]], 'R2': [[2.0,3.0],[4.0,5.0]]},
        'RBF': {'MSE': [[3.0,4.0],[5.0,6.0]], 'R2': [[4.0,5.0],[6.0,7.0]]}
        }

因为绘图需要按列拆分数据,列表索引的灵活性不足,所以需要把第二层字典中的列表转换为np.array。比如访问scores['default']['MSE']得到[[1.0,2.0],[3.0,4.0]],要提取列数据[2.0,4.0],用数组的话可以直接用scores['default']['MSE'][:, 1]实现。

我尝试了两种方法:

方法1:使用map()

import numpy as np

scores = {'default': {'MSE': [[1.0,2.0], [2.0,3.0]], 'R2': [[2.0,3.0],[3.0,4.0]]},
        'RBF': {'MSE': [[3.0,4.0],[4.0,5.0]], 'R2': [[4.0,5.0],[5.0,6.0]]}
        }

scores = map(np.array, scores)

这个方法无效,因为它把函数应用在了字典的键上,而非内层列表;它的变体虽然接近目标,但会破坏原字典的键结构:

scores = [list(map(np.array, scores[k][k2])) for k in scores.keys() for k2 in scores[k].keys()]

方法2:使用for循环

import numpy as np

scores = {'default': {'MSE': [[1.0,2.0], [2.0,3.0]], 'R2': [[2.0,3.0],[3.0,4.0]]},
        'RBF': {'MSE': [[3.0,4.0],[4.0,5.0]], 'R2': [[4.0,5.0],[5.0,6.0]]}
        }

for k in scores.keys():
    for k2 in scores[k].keys():
        scores[k][k2] = np.array(scores[k][k2])

print(scores)

这个方法可行,但需要多层循环修改字典条目,显得比较繁琐。

请问有没有更Pythonic的方式,能将函数应用于嵌套字典的最内层元素同时保留原有结构?


解决方案

1. 两层嵌套字典推导式

利用Python的字典推导式,可以简洁生成新的嵌套字典,同时完成列表到数组的转换,完全保留原结构:

import numpy as np

scores = {'default': {'MSE': [[1.0,2.0], [3.0,4.0]], 'R2': [[2.0,3.0],[4.0,5.0]]},
        'RBF': {'MSE': [[3.0,4.0],[5.0,6.0]], 'R2': [[4.0,5.0],[6.0,7.0]]}
        }

scores = {
    outer_key: {inner_key: np.array(inner_val) for inner_key, inner_val in outer_val.items()}
    for outer_key, outer_val in scores.items()
}

# 测试提取第二列数据
print(scores['default']['MSE'][:, 1])  # 输出: [2. 4.]

这种方式代码简洁、可读性强,是最直接的Pythonic实现。

2. 递归处理通用嵌套结构

如果字典的嵌套层数可能变化,递归方法可以适配任意深度的嵌套场景:

import numpy as np

def nested_list_to_array(obj):
    if isinstance(obj, dict):
        return {k: nested_list_to_array(v) for k, v in obj.items()}
    elif isinstance(obj, list):
        return np.array(obj)
    else:
        return obj

scores = {'default': {'MSE': [[1.0,2.0], [3.0,4.0]], 'R2': [[2.0,3.0],[4.0,5.0]]},
        'RBF': {'MSE': [[3.0,4.0],[5.0,6.0]], 'R2': [[4.0,5.0],[6.0,7.0]]}
        }

scores = nested_list_to_array(scores)

函数会递归遍历所有元素,遇到字典就深入处理,遇到列表就转为NumPy数组,其他类型保持不变,灵活性更高。

3. 函数式风格实现(固定两层嵌套)

如果偏好函数式编程,可以结合functools.reduce处理:

import numpy as np
from functools import reduce

scores = {'default': {'MSE': [[1.0,2.0], [3.0,4.0]], 'R2': [[2.0,3.0],[4.0,5.0]]},
        'RBF': {'MSE': [[3.0,4.0],[5.0,6.0]], 'R2': [[4.0,5.0],[6.0,7.0]]}
        }

def process_inner_dict(outer_kv):
    outer_key, outer_val = outer_kv
    inner_dict = reduce(
        lambda acc, inner_kv: {**acc, inner_kv[0]: np.array(inner_kv[1])},
        outer_val.items(),
        {}
    )
    return (outer_key, inner_dict)

scores = dict(map(process_inner_dict, scores.items()))

不过这种方式可读性不如字典推导式,适合偏好函数式编程的场景。


内容的提问来源于stack exchange,提问作者David Siret Marqués

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 09:17:16