我有一个以下格式的json文件:
[
{
"type": "BEGIN",
"id": "XYZ123"
},
{
"type": "END",
"id": "XYZ123",
},
{
"type": "BEGIN",
"id": "XYZ456"
},
{
"type": "END",
"id": "XYZ987"
},
{
"type": "END",
"id": "XYZ456"
},
{
"type": "BEGIN",
"id": "XYZ789"
},
{
"type": "",
"id": "XYZ345"
}
]
我需要输出2个文件:
valid_records.lst:
"id": "XYZ123"
"id": "XYZ456"
error_records.lst:
"id": "XYZ987"
"id": "XYZ789"
"id": "XYZ345"
即,BEGIN和END类型的块都是有效的。类型为 BEGIN 或 END 或没有的块都是错误。
这是我到目前为止尝试过的代码片段:`
valid_records=[]
error_records=[]
for rec in records:
if rec.get("type") == "BEGIN":
for rec1 in records:
if rec['id'] == rec1['id'] and rec1.get("type") == "END":
valid_records.append(rec1)
print("valid id : ", rec1['id'])
elif rec['id'] == rec1['id'] and rec1.get("type") != "END":
print("ignore, duplicate")
else:
error_records.append(rec1)
print("error id : ", rec1['id'])
这会正确打印有效的 ID(同时具有 BEGIN 和 END 的 ID)。但是,当生成错误记录时,它还包括之前识别为有效的 ID。另外,我不知道如何编码来捕获那些只有 BEGIN、END 或没有的 id。
你可以使用一个栈来跟踪已经开始但尚未结束的ID。然后,你可以遍历记录,并根据每个记录的类型和栈的状态,相应地填充有效记录和错误记录列表。
import json
def validate_records(records):
"""
验证记录并返回有效和错误的ID列表。
Args:
records: 记录列表。
Returns:
一个包含有效记录列表和错误记录列表的元组。
"""
valid_records = []
error_records = []
stack = []
for record in records:
record_type = record.get("type")
record_id = record.get("id")
if record_type == "BEGIN":
stack.append(record_id) # 开始新的块,将ID推送到栈上
elif record_type == "END":
if stack and stack[-1] == record_id:
stack.pop() # 匹配的结束,从栈上弹出ID
valid_records.append(record_id)
else:
error_records.append(record_id) # 不匹配的结束
else:
error_records.append(record_id) # 无效类型
# 添加栈中剩余的任何ID到错误记录中(未封闭的BEGIN块)
error_records.extend(stack)
return valid_records, error_records
# 从文件加载记录
with open("your_file.json", "r") as f:
records = json.load(f)
# 验证记录
valid_records, error_records = validate_records(records)
# 打印结果
print("valid_records:", valid_records)
print("error_records:", error_records)
# 将结果保存到文件
with open("valid_records.lst", "w") as f:
for record_id in valid_records:
f.write(f" \"id\": \"{record_id}\"\n")
with open("error_records.lst", "w") as f:
for record_id in error_records:
f.write(f" \"id\": \"{record_id}\"\n")
这段代码首先初始化两个列表:
valid_records
和
error_records
,以及一个空栈
stack
。然后,它循环遍历记录列表。对于每个记录,它检查其类型:
- 如果类型是“BEGIN”,则将ID推送到栈上。
-
如果类型是“END”,则检查栈是否为空以及栈顶元素是否与记录的ID匹配。如果是,则从栈中弹出该ID并将记录的ID添加到
valid_records
列表中。否则,将记录的ID添加到error_records
列表中。 -
如果类型既不是“BEGIN”也不是“END”,则将记录的ID添加到
error_records
列表中。
最后,循环结束后,如果栈中还有任何元素,则将它们添加到
error_records
列表中。这可以确保所有未封闭的“BEGIN”块都被视为错误。