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

Python如何将字符串列表解析为含numpy数组的字典

解析类MATPOWER case格式字符串为字典的通用方案

问题描述

现有如下格式的字符串列表,为类Matpower的电网算例配置文本:

['name = case1101',
 '',
 "version = '2';",
 '',
 'alpha = [',
 '\t1\t3\t0\t0\t0\t0\t1\t1.06\t0\t0\t1\t1.06\t0.94;',
 '\t2\t2\t21.7\t12.7\t0\t0\t1\t1.045\t-4.98\t0\t1\t1.06\t0.94;',
 '];',
 '',
 'beta = [',
 '\t1\t232.4\t-16.9\t10\t0\t1.06\t100\t1\t332.4\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0;',
 '\t2\t40\t42.4\t50\t-40\t1.045\t100\t1\t140\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0\t0;',
 '];',
 '',
 'gamma = [',
 '\t1\t2\t0.01938\t0.05917\t0.0528\t0\t0\t0\t0\t0\t1\t-360\t360;',
 '\t1\t5\t0.05403\t0.22304\t0.0492\t0\t0\t0\t0\t0\t1\t-360\t360;',
 '\t2\t3\t0.04699\t0.19797\t0.0438\t0\t0\t0\t0\t0\t1\t-360\t360;',
 '];',
 '']

需要将其解析为如下结构的字典:其中标量字段直接提取字符串值,数组类字段(alpha、beta、gamma)转换为浮点数组成的numpy数组。

case = {
    "name": "case1101",
    "version": "2",
    "alpha": np.array([[1.0, 3.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.06, 0.0, 0.0, 1.0, 1.06, 0.94], ...])
}

原有实现为针对单个字段硬编码正则匹配+列表推导转浮点数,存在通用性差、正则容错性低的问题,需要更简洁优雅的通用实现。
原有实现代码参考:

lines = "\n".join(lines);
search = re.search("alpha = \[([-\s0-9e.;]+)\]", lines).group(1);
np.array([[float(v) for v in r.strip().split()] for r in s.strip(';\n\t ').split(';')]);

实现思路

采用逐行扫描的状态机逻辑替代硬编码正则,无需提前预知字段名称即可自动适配所有标量、数组配置项:

  • 逐行遍历原始文本,跳过空行
  • 识别到key = [格式的行时,进入数组收集状态,缓存当前字段名
  • 识别到];格式的行时,结束数组收集,将缓存的数组内容交给numpy内置加载方法解析为浮点数组
  • 非数组收集状态下,按key = value格式解析标量字段,自动清洗值末尾的分号、包裹的引号
  • 数组解析复用numpy原生的文本加载能力,自动处理制表符、分号、科学计数法、正负号等格式,无需手动编写数值转换逻辑

完整实现代码

import numpy as np
from io import StringIO

def parse_case(raw_lines):
    case_dict = {}
    current_arr_key = None
    arr_buffer = []

    for line in raw_lines:
        stripped = line.strip()
        # 跳过空行
        if not stripped:
            continue

        # 匹配数组起始标记
        if stripped.endswith("= ["):
            current_arr_key = stripped.split("=", 1)[0].strip()
            arr_buffer = []
            continue

        # 匹配数组结束标记,解析缓存的数组内容
        if stripped == "];":
            # 替换行尾分号,拼接为符合numpy加载格式的文本
            arr_text = "\n".join(arr_buffer).replace(";", "")
            case_dict[current_arr_key] = np.loadtxt(StringIO(arr_text), dtype=np.float64)
            current_arr_key = None
            continue

        # 数组收集阶段,直接缓存当前行
        if current_arr_key is not None:
            arr_buffer.append(stripped)
            continue

        # 解析普通标量键值对
        key, value = [part.strip() for part in stripped.split("=", 1)]
        # 移除末尾分号
        value = value.rstrip(";")
        # 移除包裹的单/双引号
        if (value.startswith("'") and value.endswith("'")) or (value.startswith('"') and value.endswith('"')):
            value = value[1:-1]
        case_dict[key] = value

    return case_dict

调用方式:

case = parse_case(raw_lines)

方案优势

  • 通用性强:无需提前枚举字段名,后续新增任意标量、数组配置项都可自动解析,无需修改解析逻辑
  • 鲁棒性高:自动兼容空格/制表符缩进、行尾多余空格、科学计数法数值、带正负号数值等格式变体,不存在正则漏匹配问题
  • 性能更好:数组解析复用numpy原生C实现的文本加载逻辑,比纯Python列表推导循环转浮点数速度更快,解析大体积数组时优势明显
  • 可维护性高:逻辑为线性逐行处理,无复杂正则表达式,代码可读性远高于硬编码正则方案

内容的提问来源于stack exchange,提问作者fourloops

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 07:48:05