基于Python/AWK处理关联保单文件 修正脚本输出错误
问题描述
输入文件linked_policies.txt内容格式为「保单编号|客户编号」,示例数据如下:
0000001G|11111111 0000002G|10000018 0000002G|10000320 0000002G|10000337 0000002G|10000343 101359B|10000018 101359B|16023380 504529A|10000018 504529A|15856008 504529A|16007139 504529A|16007151 504529A|16526483 620667G|16526483 0000003G|22222222 0000003G|33333333
需要生成output_file.txt,要求每行首列为唯一保单编号,第二列为该保单直接或间接关联的所有保单(含自身,用|分隔),预期输出如下:
0000001G 0000001G 0000002G 0000002G|101359B|504529A|620667G 101359B 101359B|0000002G|504529A|620667G 504529A 504529A|0000002G|101359B|620667G 0000003G 0000003G
原Python脚本运行后输出不符合预期,例如620667G的关联列表缺少0000002G、101359B,0000002G缺少620667G,错误输出如下:
620667G 504529A|620667G 504529A 0000002G|101359B|504529A|620667G 0000003G 0000003G 0000002G 0000002G|101359B|504529A 101359B 0000002G|101359B|504529A 0000001G 0000001G
原脚本问题分析
原脚本仅将同一客户的保单直接关联,但未处理间接关联:比如620667G和504529A共享客户,504529A又和0000002G共享客户,因此620667G应间接关联0000002G,但原脚本没有迭代扩展关联关系,导致连通分量不完整。
修正后的Python脚本(适配Python 3.6及以下)
使用**并查集(Union-Find)**数据结构处理连通分量,确保所有直接/间接关联的保单被归为同一集合:
# 并查集实现 class UnionFind: def __init__(self): self.parent = {} def find(self, x): if self.parent[x] != x: self.parent[x] = self.find(self.parent[x]) # 路径压缩 return self.parent[x] def union(self, x, y): x_root = self.find(x) y_root = self.find(y) if x_root != y_root: self.parent[y_root] = x_root # 读取输入数据 with open('linked_policies.txt', 'r') as f: lines = f.readlines() # 收集所有保单编号,初始化并查集 uf = UnionFind() all_policies = set() for line in lines: policy, customer = line.strip().split('|') all_policies.add(policy) if policy not in uf.parent: uf.parent[policy] = policy # 按客户分组,将同一客户的所有保单合并 customer_policies = {} for line in lines: policy, customer = line.strip().split('|') if customer not in customer_policies: customer_policies[customer] = [] customer_policies[customer].append(policy) # 合并同一客户下的保单 for policies in customer_policies.values(): if len(policies) >= 2: first_policy = policies[0] for policy in policies[1:]: uf.union(first_policy, policy) # 构建每个保单对应的连通集合 policy_groups = {} for policy in all_policies: root = uf.find(policy) if root not in policy_groups: policy_groups[root] = set() policy_groups[root].add(policy) # 生成输出文件 with open('output_file.txt', 'w') as f: for policy in sorted(all_policies): root = uf.find(policy) group = sorted(policy_groups[root]) f.write('{} {}\n'.format(policy, '|'.join(group)))
AWK实现方案
使用AWK数组维护连通关系,通过迭代扩展关联集合,确保间接关联被覆盖:
BEGIN { FS = "|" } # 第一步:收集每个客户对应的保单列表 { cust = $2 pol = $1 cust_pols[cust] = cust_pols[cust] " " pol all_pols[pol] = 1 # 记录所有保单 } END { # 第二步:构建初始关联集合(同一客户的保单互相关联) for (c in cust_pols) { n = split(cust_pols[c], pols) for (i=1; i<=n; i++) { for (j=1; j<=n; j++) { linked[pols[i], pols[j]] = 1 linked[pols[j], pols[i]] = 1 } } } # 第三步:迭代扩展间接关联(传递闭包) changed = 1 while (changed) { changed = 0 for (p1 in all_pols) { for (p2 in all_pols) { if (linked[p1, p2]) { for (p3 in all_pols) { if (linked[p2, p3] && !linked[p1, p3]) { linked[p1, p3] = 1 linked[p3, p1] = 1 changed = 1 } } } } } } # 第四步:整理每个保单的关联列表并输出 for (p in all_pols) { group = "" for (p2 in all_pols) { if (linked[p, p2]) { group = group (group ? "|" : "") p2 } } # 对关联列表排序(模拟sorted效果) n = split(group, arr, "|") asort(arr) sorted_group = arr[1] for (i=2; i<=n; i++) { sorted_group = sorted_group "|" arr[i] } print p, sorted_group } }
运行命令:awk -f linked_policies.awk linked_policies.txt > output_file.txt
内容的提问来源于stack exchange,提问作者Adam Bradley
相关产品推荐
相关产品推荐

