在 C# 中使用 Linq 创建一个仅包含唯一值的 DataTable
Posted
技术标签:
【中文标题】在 C# 中使用 Linq 创建一个仅包含唯一值的 DataTable【英文标题】:Create a DataTable containing only unique values with Linq in C# 【发布时间】:2020-11-25 09:42:54 【问题描述】:我有一个数据表dt_Candidates
Candidate | First Name | Last Name
--------------------|----------------|---------------
John, Kennedy | John | Kennedy
Richard, Nixon | Richard | Nixon
Eleanor, Roosevelt | Eleanor | Roosevelt
Jack, Black | Jack | Black
Richard, Nixon | Richard | Nixon
我想在没有嵌套循环的情况下创建,最好使用 Linq,这是一个包含 ONLY 唯一值的 DataTable,例如 dt_Candidates2
:
Candidate | First Name | Last Name
--------------------|----------------|---------------
John, Kennedy | John | Kennedy
Eleanor, Roosevelt | Eleanor | Roosevelt
Jack, Black | Jack | Black
还有一个名为 RejectedCandidates
的列表或数组,其中包含不同的重复项
RejectedCandidates = "Richard, Nixon"
【问题讨论】:
您想根据Candidate
列强制执行唯一性吗?
我不认为 LINQ 是一个很好的工具。为表添加主键并调整创建表的逻辑以使用它(或捕获添加重复值时抛出的错误)
@PeterCsala 是的,我愿意!就整个逻辑而言,我只是再次改变主意...另一种解决方法可能是创建 RejectedCandidates 并在面对 ForEach 循环以处理单个值检查 RejectedCandidates.Any(row("Candidate").ToString.Contains)
所以它不会工作 RejectedCandidates
它可以提供可行的反馈...
@CaiusJard 感谢您提供的有用提示!我对 C# 还是很陌生,而且我曾经发现 Linq 非常方便,我认为我的逻辑被单纯的曝光效果所破坏! :)
我最喜欢的一句话是“LINQ 是一把锤子……但不是每个问题都是钉子”;)
【参考方案1】:
如前所述,我认为这里不需要 LINQ。它可以是这样的:
DataTable dt = new DataTable();
dt.Columns.Add("Candidate");
dt.Columns.Add("First");
dt.Columns.Add("Last");
dt.PrimaryKey = new [] dt.Columns["Candidate"] ; //means that dt.Find() will work
while(...)
string candidate = ...
if(dt.Rows.Find(candidate) != null)
RejectList.Add(...);
else
dt.Rows.Add(...);
避免为此在 DataTable 上使用 LINQ 的 .Any
。不仅因为它需要强制转换步骤或扩展库 (see here) 来进行操作很痛苦,而且它会使用循环来查找您寻找的信息; PrimaryKey 的内置机制使用哈希表进行更快的查找。
【讨论】:
将 PrimaryKey 添加到具有重复项的表中会抛出System.ArgumentException: These columns don't currently have unique values
或 System.Data.ConstraintException: Column 'Candidate' is constrained to be unique. Value 'Richard, Nixon' is already present
,具体取决于添加行的时间(在 PK 之前或之后)。我在您的解决方案中缺少什么吗?
您应该将 PK 添加到没有重复项的表中。答案中的代码创建一个新表,添加列,添加一个键,然后填充表。在填充时,它正在检查 if
值是否存在,如果存在,则将值放入拒绝列表中。换一种说法;无论你有什么用重复的代码填充一个表,用这个概念替换它【参考方案2】:
var dt = new DataTable
Columns = "Candidate", "First Name", "Last Name",
Rows =
new object [] "John, Kennedy", "John", "Kennedy",
new object [] "Richard, Nixon", "Richard", "Nixon",
new object [] "Eleanor, Roosevelt", "Eleanor", "Roosevelt",
new object [] "Jack, Black", "Jack", "Black",
new object [] "Richard, Nixon", "Richard", "Nixon",
;
您可以使用分组(groupBy)查找重复项,将其过滤掉,然后创建一个新的DataTable,使用DataTableExtensions.CopyToDataTable扩展方法:
var dt2 = dt.AsEnumerable()
.GroupBy(r => r["Candidate"])
.Where(g => g.Count() == 1)
.Select(g => g.First())
.CopyToDataTable();
【讨论】:
以上是关于在 C# 中使用 Linq 创建一个仅包含唯一值的 DataTable的主要内容,如果未能解决你的问题,请参考以下文章