在C#中使用Linq创建一个仅包含唯一值的DataTable

3

我有一个数据表 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,而不是嵌套循环,创建一个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”列强制执行唯一性吗? - Peter Csala
我认为LINQ不是这个问题的好工具;在表中添加一个主键,并调整创建表的逻辑以使用它(或捕获添加重复值时抛出的错误)。 - Caius Jard
@PeterCsala 是的,我有!就整个逻辑而言,我又改变了主意... 另一个解决方法可能是创建RejectedCandidates,并在面对ForEach循环以处理单个值时检查 RejectedCandidates.Any(row("Candidate").ToString.Contains) ,这样它就不会使用RejectedCandidates并且可以提供可行的反馈... - Fabio Craig Wimmer Florey
@CaiusJard 谢谢您的有用建议!我对C#还非常陌生,我发现Linq非常方便,我想我的逻辑被纯暴露效应所影响了! :) - Fabio Craig Wimmer Florey
我最喜欢的一句话是“LINQ是一把锤子..但并不是每个问题都是钉子” ;) - Caius Jard
2个回答

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。这不仅需要进行强制转换步骤或扩展库(请参见此处)来启动,而且它将使用循环来查找所需信息;内置的PrimaryKey机制使用哈希表进行更快的查找。

在带有重复项的表中添加PrimaryKey会抛出System.ArgumentException:这些列当前没有唯一值或者System.Data.ConstraintException:列'Candidate'被限制为唯一。值'Richard,Nixon'已存在取决于何时添加行(在PK之前还是之后)。您的解决方案是否遗漏了什么? - ASh
你应该将主键添加到没有重复项的表中。答案中的代码创建一个新表,添加列,添加键,然后填充表格。在填充时,它会检查值是否存在,如果存在,则将该值放入拒绝列表中。换句话说,无论你有什么填充带有重复项的表的代码,都要用这个方法替换掉。 - Caius Jard

0
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)来查找重复项,过滤它们,并使用 DataTableExtensions.CopyToDataTable扩展方法创建一个新的 DataTable:

var dt2 = dt.AsEnumerable()

            .GroupBy(r => r["Candidate"])
            .Where(g => g.Count() == 1)

            .Select(g => g.First())
            .CopyToDataTable();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接