242 lines
13 KiB
Python
242 lines
13 KiB
Python
import json
|
||
|
||
from flask_app.货物标.技术参数要求提取后处理函数 import postprocess_technical_table
|
||
|
||
import re
|
||
from collections import defaultdict
|
||
|
||
#12.27之前版本
|
||
# def extract_matching_keys(data, good_list, special_keys=None, parent_key=''):
|
||
# def get_suffix(n):
|
||
# """
|
||
# 根据数字n返回对应的字母后缀。
|
||
# 1 -> 'a', 2 -> 'b', ..., 26 -> 'z', 27 -> 'aa', 28 -> 'ab', ...
|
||
# """
|
||
# suffix = ''
|
||
# while n > 0:
|
||
# n, r = divmod(n - 1, 26)
|
||
# suffix = chr(97 + r) + suffix
|
||
# return suffix
|
||
#
|
||
# def count_matching_keys(data, patterns, special_keys, counter=None):
|
||
# """递归统计匹配键的出现次数,仅统计值为列表的键"""
|
||
# if counter is None:
|
||
# counter = defaultdict(int)
|
||
#
|
||
# if isinstance(data, dict):
|
||
# for key, value in data.items():
|
||
# clean_key = key.replace(" ", "") # 去除键中的空格
|
||
# if isinstance(value, list):
|
||
# if clean_key not in special_keys and any(pattern.match(clean_key) for pattern in patterns):
|
||
# counter[clean_key] += 1
|
||
# elif isinstance(value, dict):
|
||
# count_matching_keys(value, patterns, special_keys, counter)
|
||
# elif isinstance(data, list):
|
||
# for item in data:
|
||
# if isinstance(item, (dict, list)):
|
||
# count_matching_keys(item, patterns, special_keys, counter)
|
||
#
|
||
# return counter
|
||
#
|
||
# def process_data(data, patterns, special_keys, key_counter, suffix_map, filtered_data, parent_key):
|
||
# """递归处理数据并构建结果"""
|
||
#
|
||
# def get_suffix_label(key):
|
||
# suffix_map[key] += 1
|
||
# return get_suffix(suffix_map[key])
|
||
#
|
||
# if isinstance(data, dict):
|
||
# for key, value in data.items():
|
||
# clean_key = key.replace(" ", "") # 去除键中的空格
|
||
# if isinstance(value, list):
|
||
# # 处理值为列表的键
|
||
# if any(pattern.match(clean_key) for pattern in patterns):
|
||
# # 检查是否以特殊符号开头
|
||
# if clean_key.startswith(('▲', '★','●','■','◆','☆','△','◇','○','□')):
|
||
# symbol = clean_key[0]
|
||
# stripped_key = clean_key[1:]
|
||
# new_key = generate_key(stripped_key, parent_key, key_counter, suffix_map, special_keys)
|
||
# # 将符号添加到每个字符串的开头
|
||
# new_value = [symbol + item for item in value]
|
||
# filtered_data[new_key] = new_value
|
||
# else:
|
||
# new_key = generate_key(clean_key, parent_key, key_counter, suffix_map, special_keys)
|
||
# filtered_data[new_key] = value
|
||
# elif isinstance(value, dict):
|
||
# # 继续递归处理嵌套字典
|
||
# new_parent_key = clean_key if parent_key == '' else f"{parent_key}的{clean_key}"
|
||
# process_data(value, patterns, special_keys, key_counter, suffix_map,
|
||
# filtered_data, new_parent_key)
|
||
# elif isinstance(data, list):
|
||
# for item in data:
|
||
# if isinstance(item, (dict, list)):
|
||
# process_data(item, patterns, special_keys, key_counter, suffix_map,
|
||
# filtered_data, parent_key)
|
||
#
|
||
# def generate_key(key, parent_key, key_counter, suffix_map, special_keys):
|
||
# """生成新的键名"""
|
||
# if key in special_keys and parent_key:
|
||
# return f"{parent_key}的{key}"
|
||
# elif key_counter[key] > 1:
|
||
# suffix = get_suffix(suffix_map[key] + 1)
|
||
# suffix_map[key] += 1
|
||
# return f"{key}-{suffix}"
|
||
# return key
|
||
#
|
||
# if special_keys is None:
|
||
# special_keys = ["系统功能"] # 默认值为 ["系统功能"]
|
||
#
|
||
# # 去除 good_list 中的空格
|
||
# clean_good_list = [g.replace(" ", "") for g in good_list]
|
||
#
|
||
# # 构建匹配的正则表达式
|
||
# patterns = [re.compile(r'^' + re.escape(g) + r'(?:-\d+)?$') for g in clean_good_list]
|
||
#
|
||
# # 先统计所有匹配键的出现次数,仅统计值为列表的键
|
||
# key_counter = count_matching_keys(data, patterns, special_keys)
|
||
#
|
||
# # 初始化后缀映射
|
||
# suffix_map = {key: 0 for key, count in key_counter.items() if count > 1}
|
||
#
|
||
# # 用于存储最终结果
|
||
# filtered_data = {}
|
||
#
|
||
# # 递归处理数据
|
||
# process_data(data, patterns, special_keys, key_counter, suffix_map, filtered_data, parent_key)
|
||
#
|
||
# return filtered_data
|
||
|
||
|
||
|
||
def test_extract_matching_keys():
|
||
# 定义测试数据
|
||
data = {
|
||
"采购需求": {
|
||
"显示系统": {
|
||
"系统功能":["1","2"],
|
||
"★LED全彩显示屏": [
|
||
"1、显示尺寸:6m±0.3(W)× 1.5m±0.2(H),单屏分辨率≥3744 × 1040;",
|
||
"2 、像素间距≤1.53mm;",
|
||
"3 、亮度≥450nits, 色温: 3000-15000K 可调, 对比度: 5000:1;",
|
||
"4 、峰值功耗≤440W, 平均功耗≤146W, 带有智能(黑屏) 节电功 能, 开启智能节电功能比没开启节能 40%以上;",
|
||
"5 、水平可视角度≥160 ° , 垂直可视角度≥140 ° ;",
|
||
"6 、亮度均匀性≥97%, 刷新率≥3840 Hz , 发光点中心距偏差<3%;",
|
||
"7 、色域覆盖率≥100%, 低亮高灰: 100%亮度时, 16 bits 灰度,20% 亮度时, 12bits 灰度;",
|
||
"8 、铝底壳材质, 无风扇散热结构;",
|
||
"9 、模组电源接口采用4P 接插头, 免工具维护, 同时有防呆设计, 预防接错电源线短路而导致的烧毁模组行为,采用集成 HUB 接收卡 控制, 支持通讯状态监控;",
|
||
"10 、冗余备份, 支持双电网供电, 当其中一路交流电网跳闸后, 另 外一路电网继续供电, 实现不间断供电, 支持热备份, 当其中一块 电源失效后, 另一块电源继续工作, 从而实现不间断供电;",
|
||
"11 、屏体发光模组采用 4.5 VDC 的安全电压供电;",
|
||
"12 、彩色信号处理位数≥16bit;",
|
||
"13 、具备故障自诊及排查功能;",
|
||
"14 、 图像有降噪 、增强 、运动补偿 、色坐标变换处理 、钝 化处理无 几何失真和线性失真现象 、消除鬼影拖尾, 无“毛毛虫 ”“鬼影 ” 跟随现象;",
|
||
"15 、防护等级符合 IP6X, 显示屏具有防潮 、防尘 、防腐蚀 、防电磁 干扰 、防静电等功能, 并具有过流、短路 、过压 、欠压保护等功能;",
|
||
"16 、工作噪音声压等级一米处≤7.8 dB (A),盐雾符合 10 级要求, PCB 阻燃等级达到 UL 94 V-0 级要求, 通过 9 级烈度地震模拟实验。"
|
||
],
|
||
"☆钢结构底座及铝型材支架": [
|
||
"1 、主体钢架结构及定制型材;",
|
||
"2 、确保楼层承受力许可,按需加固楼层地面;",
|
||
"3 、钢结构。"
|
||
]
|
||
},
|
||
"摄像系统": {
|
||
"系统功能": ["a", "b"],
|
||
"☆钢结构底座及铝型材支架": [
|
||
"1 、主体钢架结构及定制型材;wwww",
|
||
"2 、确保楼层承受力许可,按需加固楼层地面;",
|
||
"3 、钢结构。"
|
||
]
|
||
},
|
||
"视频处理系统": {
|
||
"★高清视频拼控矩阵(16*16)": [
|
||
"1 、8U 切换主箱体, 支持输入 13 槽, 输出 4.5 槽, 支持 8 路高分采集, 支持冗余电源, 标配 1 个电源模块; 本项目配置输入接 口 16 路和 1 张字幕卡, 输出接口 16 路;",
|
||
"2 、设备应为纯硬件 FPGA 架构, CrossPoint 全总线交换技术, 背板 等效带宽;",
|
||
"3 、单张板卡支持 4 通道输入或输出, 紧凑型机箱,模拟视频单板卡 支持 16 路同时输入, 单卡支持 2 种信号源任意组合;",
|
||
"4、输入输出板卡可热插拔,输入板卡热插拔恢复时间 <2s,输出板 卡热插拔恢复时间<8s;",
|
||
"5 、开机时间≤10s, 启动电源至输出最总画面的时间间隔;",
|
||
"6 、平均故障时间间隔 ( MTBF ) 不小于 96000 小时, 保证设备能够 稳定运行;",
|
||
"7 、最大单机背板信号处理带宽不小于 720Gbps;",
|
||
"8、对各个输入通道采用纯硬件处理技术,采用独享带宽方式为每个 输入通道分配带宽, 切换过程中对其他信号无影响, 实现了对输入 通道的实时处理;",
|
||
"9、支持集中采集 DVI、VGA、CVBS、HDBaseT、HDMI、SDI、YPbPr 、 光纤等 2K 信号,Dual-link DVI、HDMI 1.4、DisplayPort 等 4K 信号;",
|
||
"10 、支持 DVI 、HDBaseT 、HDMI 、SDI 、光纤 、CVBS 、Ypbp r 等常见的 2K 信号输出, Dual-link DVI 、HDMI 1.4 等 4K 信号输出;",
|
||
"11、设备可实现任意一路画面的任意比例缩放、漫游、 跨屏 、叠加、 开窗;",
|
||
"12 、设备支持图像无缝实时切换功能, 无缝切换时间<20 ms ;",
|
||
"13 、支持场景保存及快速调用, 支持场景轮巡, 适应于不同的应用 场景;",
|
||
"14 、支持信号源预监功能, 支持浏览所有输入信号源的实时预览画 面;",
|
||
"15 、支持大屏图像回显, 可显示整面拼接墙的显示图像;",
|
||
"16 、支持设置拼接屏的拼缝补偿, 可精确到 1 个像素;",
|
||
"17 、支持 RRTA 分辨率实时全兼容技术, 单台 设备应支持同时控制 4 组不同分辨率的大屏幕显示;",
|
||
"18 、设备具备静态底图功能, 设备支持超大分辨率底图显示, 横纵 分辨率最大 65535 像素。"
|
||
],
|
||
"分量信号接口器": [
|
||
"用于现有视频会议专业对接高清矩阵接口器"
|
||
],
|
||
"高清四画面分割器": [
|
||
"画面预览使用, 具有画中画 、独立单画面放大功能。"
|
||
]
|
||
},
|
||
}
|
||
}
|
||
good_list = [
|
||
"★LED全彩显示屏",
|
||
"控制盒及电源",
|
||
"大屏播控系统",
|
||
"配电柜(含PLC)",
|
||
"☆钢结构底座及铝型材支架",
|
||
"电缆及信号线缆",
|
||
"控制终端",
|
||
"50寸液晶电视机",
|
||
"50寸电视机地面推车",
|
||
"高清监视器",
|
||
"★高清摄像机",
|
||
"摄像机三脚架",
|
||
"摄像机壁装架",
|
||
"摄像机控制键盘",
|
||
"★高清视频拼控矩阵(16*16)",
|
||
"分量信号接口器",
|
||
"高清四画面分割器",
|
||
"数字会议发言主机",
|
||
"方形短杆代表话筒",
|
||
"专用连接线缆",
|
||
"手持无线话筒",
|
||
"▲多点控制器",
|
||
"★多串口控制服务器",
|
||
"★综合会议管理调度平台",
|
||
"★高清会议终端(主会场)",
|
||
"★高清会议终端(分会场)",
|
||
"65寸电视机移动推车(9楼)",
|
||
"65寸液晶电视机(分会场)",
|
||
"控制平板及软件",
|
||
"鹅颈话筒",
|
||
"时序电源",
|
||
"多媒体地插盒",
|
||
"线材辅料",
|
||
"墙体拆除及修复",
|
||
"系统功能"
|
||
]
|
||
|
||
special_keys = ["系统功能", "dairy"] # 假设 'dairy' 也是特殊键
|
||
|
||
|
||
# 注意:根据您的函数逻辑,特殊键会被排除,且嵌套的 'fruits' 会被处理
|
||
# 这里我们需要根据函数实际行为调整预期输出
|
||
# 让我们根据函数逻辑重新定义预期输出
|
||
|
||
# 函数会生成新的键名,对于重复的 'fruits' 会添加后缀
|
||
# 'grains' 内的 'whole' 和 'whole-1' 也会被处理为 'whole-a', 'whole-b'
|
||
# 'chips' 和 'chips-1' 会被处理为 'chips-a', 'chips-b'
|
||
# 'dairy' 是特殊键,应被排除
|
||
# '系统功能' 和 '系统 功能' 是特殊键,应被排除
|
||
|
||
# 运行函数
|
||
result = postprocess_technical_table(data, good_list, special_keys)
|
||
|
||
# 打印结果
|
||
print("测试用例: 提取匹配键并处理各种情况")
|
||
print("good_list:", good_list)
|
||
print("special_keys:", special_keys)
|
||
print("实际输出:", json.dumps(result,ensure_ascii=False,indent=4))
|
||
|
||
# 运行测试
|
||
if __name__ == "__main__":
|
||
test_extract_matching_keys()
|