C# DataTable查找重复行并显示行号求助(列名不固定)
解决动态列DataTable查找重复行及行号问题
问题原因分析
你之前用Except的思路不对,Except是求两个集合的差集,并非用于查找重复行。而且当Linq查询结果为空时,调用CopyToDataTable()会直接抛出“The source contains no DataRows”错误——因为该方法要求源集合必须至少包含一行数据。
正确实现思路
要处理动态列的DataTable重复行,核心是按所有列的值对行进行分组,筛选出分组内行数大于1的组(即存在重复的行组),再提取这些组里的行及其对应的行号。由于列名不固定,不能硬编码列名,必须基于所有列的值来判断行是否重复。
代码实现
// 假设你的目标DataTable名为targetDt var duplicateRowsWithRowNumbers = targetDt.AsEnumerable() // 以所有列值拼接成的字符串作为分组键,确保全列值一致才会归为同一组 .GroupBy(row => string.Join("|", targetDt.Columns.Cast<DataColumn>().Select(col => row[col]))) // 筛选出包含重复行的组 .Where(group => group.Count() > 1) // 展开分组,获取每一行及其对应的行号(行号从1开始计数) .SelectMany(group => group.Select(row => new { RowData = row, RowNumber = targetDt.Rows.IndexOf(row) + 1 })) .ToList(); // 输出重复行信息 foreach (var item in duplicateRowsWithRowNumbers) { var rowContent = string.Join(", ", targetDt.Columns.Cast<DataColumn>().Select(col => $"{col.ColumnName}={item.RowData[col]}")); Console.WriteLine($"重复行号:{item.RowNumber},行内容:{rowContent}"); } // 若需将重复行存入新DataTable if (duplicateRowsWithRowNumbers.Any()) { DataTable duplicateDt = duplicateRowsWithRowNumbers.Select(item => item.RowData).CopyToDataTable(); // 给新表添加行号列 duplicateDt.Columns.Insert(0, "行号", typeof(int)); foreach (DataRow row in duplicateDt.Rows) { row["行号"] = targetDt.Rows.IndexOf(row) + 1; } }
关键说明
- 分组键设计:用
string.Join拼接所有列值作为分组标识,若列值可能包含分隔符|,可替换为其他无冲突字符(如\t)。 - 避免空结果报错:调用
CopyToDataTable()前,先用Any()判断是否存在数据,从根源避免空集合报错。 - 行号计算:通过
targetDt.Rows.IndexOf(row)+1获取行号,将DataTable默认的0起始索引转为日常1起始的计数方式。
内容的提问来源于stack exchange,提问作者user25527959
相关产品推荐
相关产品推荐

