将DataRow集合与List<T>进行比较

7

我有一个 List<string> 和一个 DataTable。

DataRow 中的一列是 ID。List 包含这些 ID 的实例。

DataTable 在计时器上被填充。

我想要从 List 返回不在 DataTable 中的项到另一个列表中。

3个回答

17

你需要做类似这样的事情

var tableIds = table.Rows.Cast<DataRow>().Select(row => row["ID"].ToString());

var listIds = new List<string> {"1", "2", "3"};

return listIds.Except(tableIds).ToList();

您可以将数据表中的行转换为IEnumerable集合,然后从每个行中选择“ID”列的值。 然后,您可以使用Enumerable.Except扩展方法获取在刚刚创建的集合中不存在于列表中的所有值。

如果您需要获取表中存在但不在列表中的值,只需反转listIds和tableIds即可。


1
+1 .Cast是我错过的链接,它可以让我使用所有那些美妙的扩展方法。 - Alain

1
如果您的表格是这样的:
DataTable dt = new DataTable();
dt.Columns.Add("ID");
DataRow dr = dt.NewRow();
dt.PrimaryKey = new DataColumn[] {dt.Columns[0]};
dr["ID"] = "1";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["ID"] = "2";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["ID"] = "3";
dt.Rows.Add(dr);

而列表大致如下:

List<string> ls = new List<string>{"1","2","4"};

我们可以通过以下方式获取列表中存在但数据表中不存在的项目:
var v = from r in ls
                where !dt.Rows.Contains(r)
                select r;
        v.ToList();

1

通过使用HashSet<T>来实现相对高效率(并注意到从DataRow中获取数据的最快方法是通过DataColumn索引器):

        HashSet<int> ids = new HashSet<int>();
        DataColumn col = table.Columns["ID"];
        foreach (DataRow row in table.Rows)
        {
            ids.Add((int)row[col]);
        }
        var missing = list.Where(item => !ids.Contains(item.ID)).ToList();

我还没有测试过这两种方法,但你认为你的答案比bdowden的更有效吗? - Jon
除非您有大量数据,否则差别不会很大,但是略微有所不同。字符串索引器会为每一行查找列。在大多数情况下,请坚持使用您认为最简单和最易于理解的方法(只有在需要时才进行进一步优化)。 - Marc Gravell
噢,而且在Cast/Select中还有更多的枚举器(=更多的开销),但再次强调:通常不会产生重大差异。 - Marc Gravell

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