例如,我的DataTable看起来像这样DataTable,我希望使用LINQ创建一个仅包含“User”元素的列表,且不重复出现。
我尝试使用的代码是:
InvoiceList = InvoiceDT.AsEnumerable().GroupBy(Function(r) r("User").ToString).ToList(Function(g) g.ToList())
但是对于我来说并不起作用,因为我是LINQ的新手,仍然在形成结构方面存在问题。
InvoiceList = InvoiceDT.AsEnumerable().GroupBy(Function(r) r("User").ToString).ToList(Function(g) g.ToList())
但是对于我来说并不起作用,因为我是LINQ的新手,仍然在形成结构方面存在问题。
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传递委托,它不接受委托(而且你也不会对g进行ToList操作,因为它是包含所有变量属性的数据行列表)。
我们将IGrouping(类似于对象列表,它们共享列表中IGrouping表示的属性键)重塑成一系列字符串键,通过选择键然后ToList 它来实现。
开发人员之间存在许多关于ToList和ToArray等事项的往返 - 有些人普遍使用ToList,因为对于元素数量未知的集合,列表和数组都会以相同的方式增长和调整大小,但是使用ToArray需要一个附加的调整大小步骤来修剪任何未使用的插槽。通常,在整体性能考虑方面,这大多是微不足道的,并应该权衡释放内存与调整大小的好处。深入了解细节已经超出了本回答的范围,但您可以阅读一些巨大的博客文章来了解更多信息。
我个人认为,通过调用生成相关类型结果的方法来生成明智的代码更为重要;如果需要列表功能(添加/插入/删除),我就使用ToList
。如果一个数组适合后续用途(读/写/随机访问,无插入或删除),我更喜欢ToArray
。如果我只会枚举它,我根本不需要To...
任何东西 - 我只需ForEach查询结果,这可能比其他任何方法都更能提高性能,因为它意味着我可能不必枚举整个集合(如果我早停)或一次性分配内存(如果我正在写入套接字或文件)。
关于ToString的使用,如果您认为您将陷入每列都执行ToString以获取字符串的模式中,则值得避免。如果该列已经是字符串,则将DataRow.Item给你的对象转换为字符串是可以接受的方法。如果该列是另一种类型,则最好将其转换为:
DirectCast(r("Age"), Integer)
r.Field(Of Integer)("Age")
问题在于,它很冗长,难看,并且智能感应不帮助您编写Age或知道它是Int。在VB中的LINQ已经够啰嗦了,不要再加油了。如果您正在使用已知结构的数据表,那么创建强类型表会更加美观:
然后像这样使用:
Dim dt as new AccountsDataSet.InvoicesDataTable
用以下方式填充:
dt.AddInvoicesRow("John Smith", ... other properties here)
可以这样查询:
dt.Select(Function(r) r.User).Distinct()
使用对象形式访问列名比使用字符串更方便,而且它们是需要转换的对象。
将数据集生成器视为一种快速、可视的方式来创建具有命名、类型属性的poco类。
试试这个
dim list as List(of string) = InvoiceDT.Rows.
Cast(of DataRow)().
Select(Function(r) r("User").ToString()).
Distinct().
ToList()
在这里,你将行集合转换为 IEnumerable(of DataRow)
,其余部分都是琐事。
InvoiceDT.AsEnumerable()
,我认为这是一个多余的扩展方法对于 DataTable
。例如在 fiddle 中,VB 可以通过添加 System.Data.DataSetExtensions
获得该方法,但对于 C# 我并不需要添加它。 - T.S.
ToList
,除非你正在使用需要数组的 API,因为相较于ToList
,ToArray
可能需要额外的分配。 - NetMager("User").ToString()
更改为r.Field(Of String)("User")
。 - jmcilhinney