2024-11-01 17:55:26 +08:00

144 lines
6.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- encoding:utf-8 -*-
import json
import re
def is_numeric_key(key):
# 这个正则表达式匹配由数字、点、括号中的数字或单个字母(小写或大写)组成的字符串,
# 字母后跟数字,或数字后跟字母,单个字母后跟点,但不能是字母-数字-字母的组合
pattern = r'^[\d.]+$|^\(\d+\)$|^\d+$|^[a-zA-Z]$|^[a-zA-Z]\d+$|^\d+[a-zA-Z]$|^[a-zA-Z]\.$'
return re.match(pattern, key) is not None
def contains_number_or_index(key, value):
# 判断值是否是数字或数字字符串
is_number = isinstance(value, (int, float)) or (isinstance(value, str) and value.isdigit())
# 判断键是否包含 "序号"
contains_index = '序号' in key
# 判断值中是否包含数字
contains_digit = isinstance(value, str) and re.search(r'\d+', value)
# 判断值中是否包含中文字符
contains_chinese = isinstance(value, str) and re.search(r'[\u4e00-\u9fff]', value)
# 如果值中包含数字但也有中文字符,则保留(返回 False
if contains_digit and contains_chinese:
return False
# 如果值是数字或包含数字,且不包含中文字符,或者键包含 "序号",返回 True
return is_number or contains_index or contains_digit
def preprocess_dict(data):
if isinstance(data, dict):
if len(data) > 1:
# 检查是否所有值都是 "" 或 "/"
if all(v == "" or v == "/" or (isinstance(v, list) and not v) for v in data.values()):
return list(data.keys())
else:
processed = {}
for k, v in data.items():
if not contains_number_or_index(k, v):
processed_v = preprocess_dict(v)
if processed_v != "": # 只添加非空值
processed[k] = processed_v
return processed
else:
return {k: preprocess_dict(v) for k, v in data.items()}
elif isinstance(data, list):
return [preprocess_dict(item) for item in data]
else:
return data
def process_dict(data):
"""
递归处理字典,将符合条件的键值对进行转换。
如果键是数字或特定格式的字符串,则将其值放入 'items' 列表中并排序。
对于非数字键,如果对应的值是列表且列表中只有一个元素,则将其展平为单个元素。
Args:
data (dict): 输入的字典数据。
Returns:
dict 或 list 或 原始数据类型: 处理后的数据结构。
"""
if not isinstance(data, dict):
return data
result = {}
numeric_keys = []
non_numeric_keys = {}
# 分类键为数字键和非数字键
for key, value in data.items():
if is_numeric_key(key):
numeric_keys.append((key, value))
else:
non_numeric_keys[key] = value
# 处理数字键,将其值递归处理后放入 'items' 列表中
if numeric_keys:
def sort_key(item):
key = item[0]
if re.match(r'^\d+$', key): # 纯整数
return (int(key),)
elif re.match(r'^\d+\.\d+$', key): # 单层小数点
return (float(key),)
else: # 多层序号,按字符串处理
return tuple(map(int, key.split('.')))
# 按键排序,确保顺序一致
numeric_keys_sorted = sorted(numeric_keys, key=sort_key)
result['items'] = [process_dict(item[1]) for item in numeric_keys_sorted]
# 处理非数字键
for key, value in non_numeric_keys.items():
if isinstance(value, list):
processed_list = []
for item in value:
if isinstance(item, dict):
# 处理字典中只有一个键值对的情况
if len(item) == 1:
processed_item = process_dict(list(item.values())[0])
else:
processed_item = process_dict(item)
else:
processed_item = process_dict(item)
# 如果处理后的项是只包含一个元素的列表,则展平它
if isinstance(processed_item, list) and len(processed_item) == 1:
processed_item = processed_item[0]
processed_list.append(processed_item)
# 新增逻辑:如果 processed_list 只有一个元素,则将其展平为单个元素
if len(processed_list) == 1:
result[key] = processed_list[0]
else:
result[key] = processed_list
else:
# 如果值不是列表,直接递归处理
result[key] = process_dict(value)
# 如果结果只有一个键 'items',则直接返回 'items' 列表
if len(result) == 1 and 'items' in result:
return result['items']
# 检查如果所有键对应的值都是空列表,则将键名转换成列表项
if all(isinstance(v, list) and not v for v in result.values()):
return list(result.keys())
return result
data={
"资格性审查": {
"1": "供应商应具备《政府采购法》第二十二条规定的条件,提供相关材料。",
"2": "法人或者其他组织的营业执照等证明文件,自然人的身份证明;",
"3": "财务状况报告,依法缴纳税收和社会保障资金的声明函;",
"4": "具备履行合同所必需的设备和专业技术能力的证明材料;",
"5": "未被列入信用记录名单声明函;",
"6": "参加政府采购活动前 3年内在经营活动中没有重大违法记录的书面声明",
"7": "具备法律、行政法规规定的其他条件的证明材料;",
"8": "招标文件第一章“投标人资格要求”中有特殊要求的,投标人应提供其符合特殊要求的证明材料或者情况说明;",
"9.1.1": "未被列入信用记录名单声明函;",
"10.1.1": "参加政府采购活动前 3年内在经营活动中没有重大违法记录的书面声明",
"11": "具备法律、行政法规规定的其他条件的证明材料;",
"12": "招标文件第一章“投标人资格要求”中有特殊要求的,投标人应提供其符合特殊要求的证明材料或者情况说明;"
}
}
res1=process_dict(preprocess_dict(data))
print(json.dumps(res1,ensure_ascii=False,indent=4))