疫苗接种记录文本解析字段错位:如何修正代码实现正确映射
疫苗接种记录解析错误修正问题
原始数据
vaccinations_text = """ |Entry #|Vaccine|Type of vaccine|Lot #|Manufacturer|VIS edition date|Date given|Vaccinator (initials)| |1|Influenza|H1N1|2F03930|NOV|8/24/09|12/7/09|PLE| |2|Tetanus, Diphtheria, Pertussis|Td|U049393AA|ASP|4/2/95|10/7/95|ODK| |3|Tetanus, Diphtheria, Pertussis|Td|U049393AA|ASP|4/2/95|11/7/95|WMK| |4|Tetanus, Diphtheria, Pertussis|Td|U049393AA|ASP|4/2/95|4/7/96|CPK| |5|Tetanus, Diphtheria, Pertussis|Tdap|AC9349239AA|GSK|2/12/07|3/1/07|CPK| |6|Measles, Mumps, Rubella|MMR|02302L|DVX|9/7/15|11/4/15|WNK| |7|Hepatitis B|Heplisav-B|TD02302|DVX|9/9/16|10/4/18|WNK| """
需求
将上述字符串解析为vaccination_records列表,每个元素是由(列头,对应值)元组组成的列表,例如Entry 1应解析为:
[('Entry #', 1), ('Vaccine', 'Influenza'), ('Type of vaccine', 'H1N1'), ...]
所有日期需转换为dt.date类型。
错误代码
import re import datetime as dt vaccination_records = [] lines = vaccinations_text.strip().split('\n') headers = lines[0].split('|')[1:-1] date_pattern = re.compile(r'(\d{1,2}/\d{1,2}/\d{2})') for line in lines[1:]: values = line.split('|')[1:-1] record = [('Entry #', int(values[0]))] for header, value in zip(headers, values[1:]): if header == 'Date given': date = date_pattern.search(value) if date: date = dt.datetime.strptime(date.group(0), '%m/%d/%y').date() record.append((header, date)) else: record.append((header, value)) vaccination_records.append(record)
错误结果示例
Entry 1的解析结果出现字段错位:
[('Entry #', 1), ('Entry #', 'Influenza'), ('Vaccine', 'H1N1'), ('Type of vaccine', '2F03930'), ('Lot #', 'NOV'), ('Manufacturer', '8/24/09'), ('VIS edition date', '12/7/09')]
问题原因与修正方案
错误原因
代码手动添加了('Entry #', int(values[0]))到record后,又用zip(headers, values[1:])遍历配对,导致headers的第一个元素('Entry #')和values[1:]的第一个元素('Influenza')错误配对,出现重复字段,后续所有字段全部错位。同时原代码只处理了Date given一个日期字段,遗漏了VIS edition date。
修正后的代码
import datetime as dt vaccination_records = [] lines = vaccinations_text.strip().split('\n') headers = lines[0].split('|')[1:-1] for line in lines[1:]: values = line.split('|')[1:-1] record = [] for header, value in zip(headers, values): if header == 'Entry #': # 转换Entry #为整数 record.append((header, int(value))) elif header in ['VIS edition date', 'Date given']: # 转换两个日期字段为dt.date类型 date = dt.datetime.strptime(value, '%m/%d/%y').date() record.append((header, date)) else: record.append((header, value)) vaccination_records.append(record)
关键修改点
- 移除手动添加的第一个字段,直接遍历所有
headers和values的完整配对,确保字段一一对应。 - 同时处理
Entry #的整数转换,以及两个日期字段的类型转换,避免遗漏。 - 去掉冗余的正则匹配,日期格式固定,直接用
strptime解析即可。
验证结果
Entry 1的正确解析结果:
[('Entry #', 1), ('Vaccine', 'Influenza'), ('Type of vaccine', 'H1N1'), ('Lot #', '2F03930'), ('Manufacturer', 'NOV'), ('VIS edition date', datetime.date(2009, 8, 24)), ('Date given', datetime.date(2009, 12, 7)), ('Vaccinator (initials)', 'PLE')]
内容的提问来源于stack exchange,提问作者Rstudyer
相关产品推荐
相关产品推荐

