如何修复从CSV文件提取唯一值时的重复输出问题?
问题描述
我想从CSV文件中提取每一列的唯一值,然后输出到新文件里。
示例输入CSV内容:
12,life,car,good,exellent 10,gift,truck,great,great 11,time,car,great,perfect
期望输出的新文件内容:
12,10,11 life,gift,time car,truck good,great exellent,great,perfect
我编写了如下Python代码:
def attribute_values(in_file, out_file): fname = open(in_file) fout = open(out_file, 'w') # get the header line header = fname.readline() # get the attribute names attrs = header.strip().split(',') # get the distinct values for each attribute values = [] for i in range(len(attrs)): values.append(set()) # read the data for line in fname: cols = line.strip().split(',') for i in range(len(attrs)): values[i].add(cols[i]) # write the distinct values to the file for i in range(len(attrs)): fout.write(attrs[i] + ',' + ','.join(list(values[i])) + '\n') fout.close() fname.close()
但当前代码输出存在重复内容:
12,10 life,gift car,truck good,great exellent,great 12,10,11 life,gift,time car,car,truck good,great exellent,great,perfect
请问如何修复该代码以得到期望输出?
问题原因与修复方案
问题所在
你的代码把写入文件的逻辑放在了读取每一行数据的循环内部,导致每读一行就把当前收集到的列唯一值写一遍,因此出现重复输出。另外还有两个小问题:
- 错误地将表头属性名写入了输出(
attrs[i] + ','),但期望输出不含表头; - 使用
set存储值会导致顺序不确定(集合无序),如果需要保留值首次出现的顺序,需要改用有序结构。
修正后的代码
def attribute_values(in_file, out_file): # 用with语句自动管理文件生命周期,避免遗漏关闭 with open(in_file, 'r') as fname, open(out_file, 'w') as fout: # 读取表头确定列数(若输入无表头,可直接读取第一行数据) header = fname.readline() cols_count = len(header.strip().split(',')) # 用dict.fromkeys维护有序唯一值(Python3.7+字典默认有序) column_values = [dict.fromkeys([]) for _ in range(cols_count)] # 遍历所有数据行收集唯一值 for line in fname: cols = line.strip().split(',') for idx, val in enumerate(cols): column_values[idx][val] = None # 所有数据收集完成后统一写入结果 for vals_dict in column_values: fout.write(','.join(vals_dict.keys()) + '\n')
代码说明
- 文件管理:
with语句会自动处理文件的打开和关闭,比手动调用close()更安全; - 去重与顺序:用
dict.fromkeys()替代set,既实现自动去重,又能保留值首次出现的顺序; - 写入时机:将写入逻辑移到所有数据读取完成之后,确保只输出最终收集到的每列唯一值,避免重复写入;
- 格式修正:移除了原代码中写入表头属性名的逻辑,匹配期望输出格式。
无表头场景适配
如果输入CSV没有表头,直接读取第一行数据初始化列存储即可:
def attribute_values(in_file, out_file): with open(in_file, 'r') as fname, open(out_file, 'w') as fout: # 读取第一行数据确定列数并初始化 first_line = fname.readline() cols = first_line.strip().split(',') cols_count = len(cols) column_values = [dict.fromkeys([cols[idx]]) for idx in range(cols_count)] # 读取剩余行数据 for line in fname: cols = line.strip().split(',') for idx, val in enumerate(cols): column_values[idx][val] = None # 写入结果 for vals_dict in column_values: fout.write(','.join(vals_dict.keys()) + '\n')
内容的提问来源于stack exchange,提问作者helppls
相关产品推荐
相关产品推荐

