C# WinForm 导入CSV至DataGrid/DataTable前如何按ID与名称组合去重
C# WinForm CSV导入双字段去重实现
业务需求说明
- 原有CSV导入逻辑仅支持整行文本简单去重,无法满足实际业务规则
- 去重判定规则:仅当记录的ID字段与名称字段同时完全匹配时,才判定为重复记录并移除
- 保留规则:ID重复但名称不同、名称重复但ID不同的记录需全部保留,不可误删
- 去重操作必须在数据写入DataTable、绑定DataGridView控件之前完成
原有实现的问题
- 导入逻辑中使用
Lines.Distinct()做整行去重,没有针对ID+名称双字段的匹配判断逻辑 - 硬编码按逗号拆分行解析,未定位业务字段位置,无法适配列顺序变动的CSV文件
修正后的完整代码实现
using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Linq; using System.Windows.Forms; namespace Export_Import_CSV { public partial class Form1 : Form { // 全局DataTable存储导入数据 private readonly DataTable dt = new DataTable(); public Form1() { InitializeComponent(); // 初始化DataTable结构 BindDataGridView(); } /// <summary> /// 初始化DataTable列结构 /// </summary> private void BindDataGridView() { // 根据实际CSV列定义,此处示例为ID、Name及其他业务列 dt.Columns.Add("ID", typeof(string)); dt.Columns.Add("Name", typeof(string)); // 可按需补充其他业务列 } /// <summary> /// 导入按钮点击事件 /// </summary> private void ImportBtn_Click(object sender, EventArgs e) { dt.Rows.Clear(); OpenFileDialog dlg = new OpenFileDialog(); dlg.Multiselect = false; dlg.Filter = "CSV文件(*.csv)|*.csv"; if (DialogResult.OK == dlg.ShowDialog()) { string path = dlg.FileName; ImportCsvWithDedup(path); MessageBox.Show("导入流程执行完成"); } } /// <summary> /// 带ID+名称双字段去重的CSV导入方法 /// </summary> /// <param name="filePath">CSV文件路径</param> private void ImportCsvWithDedup(string filePath) { // 读取所有非空行 string[] allLines = File.ReadAllLines(filePath) .Where(line => !string.IsNullOrWhiteSpace(line)) .ToArray(); // 校验文件行数 if (allLines.Length < 2) { MessageBox.Show("CSV文件中无有效数据行"); return; } // 解析表头,定位ID、Name列的索引 string[] headerCells = allLines[0].Split(','); int idColIndex = Array.FindIndex(headerCells, cell => cell.Trim().Equals("ID", StringComparison.OrdinalIgnoreCase)); int nameColIndex = Array.FindIndex(headerCells, cell => cell.Trim().Equals("Name", StringComparison.OrdinalIgnoreCase)); // 校验必需列是否存在 if (idColIndex == -1 || nameColIndex == -1) { MessageBox.Show("CSV文件缺少ID或Name列,无法执行去重校验"); return; } // 存储已出现的ID+名称组合,用于快速去重 HashSet<string> existedCombos = new HashSet<string>(); int filteredDuplicateCount = 0; // 从第二行开始遍历数据行 for (int i = 1; i < allLines.Length; i++) { string[] rowCells = allLines[i].Split(','); // 跳过列数不足的异常行 if (rowCells.Length <= Math.Max(idColIndex, nameColIndex)) { continue; } string idValue = rowCells[idColIndex].Trim(); string nameValue = rowCells[nameColIndex].Trim(); // 生成双字段唯一匹配键 string uniqueKey = $"{idValue}|{nameValue}"; // 判断是否为重复行 if (!existedCombos.Add(uniqueKey)) { filteredDuplicateCount++; continue; } // 非重复行写入DataTable DataRow dr = dt.NewRow(); for (int colIndex = 0; colIndex < dt.Columns.Count; colIndex++) { dr[colIndex] = colIndex < rowCells.Length ? rowCells[colIndex] : string.Empty; } dt.Rows.Add(dr); } // 绑定数据到DataGridView dataGridView1.DataSource = dt; // 提示去重结果 if (filteredDuplicateCount > 0) { MessageBox.Show($"导入完成,共过滤{filteredDuplicateCount}条ID与名称同时匹配的重复记录"); } } } }
实现效果说明
- 严格匹配去重规则:仅ID、名称双值同时一致的记录会被过滤,单字段重复的记录全部保留
- 性能优化:使用HashSet存储唯一组合,整体遍历时间复杂度为O(n),适配大体积CSV文件导入场景
- 异常兼容:对列缺失、行格式不规范的情况做了校验,避免程序运行异常崩溃
内容的提问来源于stack exchange,提问作者Divya Shree
相关产品推荐
相关产品推荐

