VB.Net中数据表的每列中的最大字符串长度
本文关键字:字符串 Net 数据表 VB | 更新日期: 2023-09-27 17:58:38
我需要知道DataTable(使用VB.Net)每列的最大当前长度
我需要每列的最大.ToString.Length
。
我在这里找到了下面的C#代码,但我无法将其翻译成VB.Net
List<int> maximumLengthForColumns =
Enumerable.Range(0, dataTable.Columns.Count)
.Select(col => dataTable.AsEnumerable()
.Select(row => row[col]).OfType<string>()
.Max(val => val.Length)).ToList();
编辑
我终于能够将代码翻译成可读性更强的vb.net,但无法适应我的需求:
maximumLengthForColumns = Enumerable.Range(0, DT.Columns.Count).
Select(Function(col)
Return DT.AsEnumerable().Select(Function(row)
Return row(col)
End Function).OfType(Of String)().Max(Function(v)
Return v.Length
End Function)
End Function).ToList()
DataTable
公开一个Columns
属性,该属性是列定义的集合。每个项(实际上是DataColumn
类型)都暴露允许的最大长度。您找到的代码示例只查看存储在表中的数据。也就是说,它返回的是数据使用的当前最大长度,而不是列支持的最大长度。
要检索允许的最大长度,只需扫描提供的DataTable对象的DataColumns属性并使用MaxLength
属性。
下面是一个使用LINQ语法的片段:
Dim maximumLengthForColumns = From c in dataTable.Columns.Cast(Of DataColumn)
Order By c.Ordinal
Select c.MaxLength
它的实际类型并不完全是List。是IQueryable(Of Integer)
。您可以使用.ToList()
强制枚举和转换,而不是让它闲置,直到您真正需要使用结果为止。如果您只需要枚举结果,您可以作为IQueryable离开,因为接口确实继承了IEnumerable。
我不需要包含订单依据条款。这可能会减慢实际执行速度。但是,如果您的数据表中有太多的列,以至于这成为一个真正的瓶颈,则需要将其取出,并给出一些其他补救说明。
为什么我没有添加筛选子句(Select
)?MaxLength
属性是为所有列公开的,而不仅仅是字符串类型。而且,一个简单的结果枚举可能会与原始数据表中的列数相匹配。如果没有,请随意将该子句添加到LINQ语句中。
Where c.DataType = GetType(String)
发布的自我回答是迭代所有列,并将它们视为字符串列,即使它们不是。也就是说,它正在测量和收集不是字符串的数据的.ToString
长度(这似乎不是所需的)。
非字符串数据列可以通过以下方式省略:
Dim MaxColLen As New Dictionary(Of String, Integer)
For Each dc As DataColumn In dtSample.Columns
If dc.DataType Is GetType(String) Then
MaxColLen.Add(dc.ColumnName, 0)
For Each dr As DataRow In dtSample.Rows
If dr.Field(Of String)(dc.ColumnName).Length > MaxColLen(dc.ColumnName) Then
MaxColLen(dc.ColumnName) = dr.Field(Of String)(dc.ColumnName).Length
End If
Next
End If
Next
注意,它使用For Each
来减少代码中的混乱,并允许使用DataRow
扩展,如Field<T>()
。就我个人而言,我认为Field(Of T)(Col)
比DT.Rows(x)(Col).ToString
更可读,尽管如果确实想要测量非字符串数据,那么在非文本数据上使用它肯定会崩溃。
请注意,循环跳过非字符串列。要找到715000行中最长的文本,原始文本需要约34毫秒,而以上文本需要约9毫秒。
相同字典方法的linqy版本(带有解释步骤的注释):
' a) look at cols as cols
' b) just the string ones
' c) get the name and inital zed value to an Anonymous type
' d) convert to a dictionary of String, Int to store the longest
Dim txtCols = dtSample.Columns.Cast(Of DataColumn).
Where(Function(c) c.DataType = GetType(String)).
Select(Function(q) New With {.Name = q.ColumnName, .Length = 0}).
ToDictionary(Of String, Int32)(Function(k) k.Name, Function(v) v.Length)
' get keys into an array to interate
' collect the max length for each
For Each colName As String In txtCols.Keys.ToArray
txtCols(colName) = dtSample.AsEnumerable().
Max(Function(m) m.Field(Of String)(colName).Length)
Next
对于相同的715k行,这种形式大约需要12毫秒。扩展方法几乎总是比较慢,但这些差异都不值得担心。
您还必须翻译这些lambdas:
Dim maximumLengthForColumns As List(Of Integer) = Enumerable.Range(0, dataTable.Columns.Count).Select(Function(col) dataTable.AsEnumerable().Select(Function(row) row(col)).OfType(Of String)().Max(Function(val) val.Length)).ToList()
非LINQ答案。。。
Dim maximumLengthForColumns As New List(Of Integer)
For i As Integer = 0 To dtb.Columns.Count - 1
maximumLengthForColumns.Add(dtb.Columns(i).MaxLength)
Next i
如果列的大小不受限制,则MaxLength
属性返回-1
我被迫按照@Putonix所说的那样,在数据表上使用循环,原因有两个:
1) 我无法使用翻译后的C#
代码,因为即使所有单元格都有值,它也会给我错误"序列不包含元素",而且它似乎只为字符串字段编写
目前,我的知识还不足以成功编辑此代码,从而使其适应我的需求。
2) 建议使用MaxLength
的2个答案并不能满足我的需求,因为我需要的是每列的当前长度,而不是允许的最大长度。
感谢所有帮助的人
这是我使用的代码:
Dim MaxColLen As New Dictionary(Of String, Integer)
For y As Integer = 0 To DT.Columns.Count - 1
Dim Col As String = DT.Columns(y).ColumnName
MaxColLen.Add(Col, 0)
For x As Integer = 0 To DT.Rows.Count - 1
If DT.Rows(x)(Col).ToString.Length > MaxColLen(Col) Then
MaxColLen(Col) = DT.Rows(x)(Col).ToString.Length
End If
Next
Next