首页 > 解决方案 > 从 DataTable LINQ 列创建元素列表

问题描述

我想知道如何将 DataTable 的列的元素转换为字符串类型的列表,对元素进行分组以避免重复。

例如,我的 DataTable 看起来像这个 DataTable

我想制作一个仅包含“用户”元素的列表,而不使用 LINQ 重复。

我试图使用的代码是

InvoiceList = InvoiceDT.AsEnumerable().GroupBy(Function(r) r("User").ToString).ToList(Function(g) g.ToList())

但这对我不起作用,因为我是 LINQ 的新手并且仍然在构建结构时遇到问题。

标签: vb.netlinqdatatableuipath

解决方案


我会用这个:

InvoiceList = InvoiceDT.AsEnumerable().Select(Function(r) r("User").ToString()).Distinct().ToList()

如果你想要一个 GroupBy 解决方案,它是

InvoiceList = InvoiceDT.AsEnumerable().GroupBy(Function(r) r("User").ToString()).Select(Function(g) g.Key).ToList()

您的代码出错的地方是试图将委托传递给 ToList;它不需要一个(你也不会 ToList g ,因为它是具有所有不同属性的数据行的列表)。

为了将 groupby 生成的 IGrouping(类似于所有共享相同 Key 的对象列表,这是 IGrouping 表示的列表的属性)重塑为字符串 Keys 序列,我们选择 Key,然后选择ToList


开发人员之间在 ToList 与 ToArray 之类的问题上存在很多争论——有些人普遍使用 ToList,因为对于未知数量元素的集合,列表和数组都会以相同的方式重复增长和调整大小,但使用 ToArray 需要最后一个额外的调整大小步骤以修剪任何未使用的插槽。大多数情况下,就整体性能考虑而言,这是微不足道的,应该权衡释放内存与修剪的好处。进入更详细的细节远远超出了这个答案的范围,但你可以阅读一些关于它的巨大博客文章

我个人认为更重要的是通过调用产生相关类型的方法来生成合理的代码,具体取决于您打算用它做什么;如果我ToList需要列表功能(添加/插入/删除)。我更喜欢ToArray数组是否适合后续用途(读/写/随机访问,不插入或删除),如果我只会枚举它我什么都不做To...- 我只是 ForEach 查询的结果,这比其他任何事情都可以提供更大的性能提升,因为这意味着我可能不必枚举整个集合(如果我提前停止)或一次全部分配内存为此(如果我正在写入套接字或文件)

关于 ToString 的使用;如果您认为自己会陷入这样一种模式,即在每一列上都这样做只是为了得到一个字符串,那么这是值得避免的。如果该列已经是一个字符串,那么将 DataRow.Item 提供给您的对象放入字符串中是一种可接受的方式。如果该列是另一种类型,最好转换它:

  • DirectCast(r("Age"), Integer)
  • r.Field(Of Integer)("Age")

问题是,它冗长且丑陋,并且智能感知无法帮助您编写 Age 或知道它是 Int。VB 中的 LINQ 对于冗长的内容来说已经够糟糕了,而无需在火上浇油。如果您正在使用已知结构的数据表,那么如果您制作强类型数据表会更好:

  • 将 DataSet 类型的新文件添加到您的项目中
  • 打开它以显示设计表面。在属性网格中将其称为合理的东西,例如 AccountsDataSet
  • 右键单击,添加表,将其命名为发票
  • 右键单击空表,添加列,将其命名为用户

然后像这样使用它:

Dim dt as new AccountsDataSet.InvoicesDataTable

像这样填充它:

dt.AddInvoicesRow("John Smith", ... other properties here)

像这样查询它:

dt.Select(Function(r) r.User).Distinct()

比通过字符串访问列名并让它们成为需要强制转换的对象要好得多。

将数据集生成器视为一种快速、直观地创建具有命名、类型化属性的 poco 类的方法


推荐阅读