我需要知道DataTable每列的最大当前长度(使用VB.Net)
我需要每列最多.ToString.Length
。
我找到了下面的C#代码here,但我无法将其翻译为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()
答案 0 :(得分:2)
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)
。 Ycan使用.ToList()
来强制枚举和转换,而不是让它闲置,直到您确实需要使用结果。如果您只需要枚举结果,就可以保留为IQueryable,因为接口确实从IEnumerable继承。
我不需要包含Order By子句。它可能会减慢实际执行速度。但是,如果您的数据表中有这么多列,这将成为一个真正的瓶颈,您需要被取回并给出一些其他补救说明。
为什么我没有添加过滤条款(Select
)?所有列都公开MaxLength
属性,而不仅仅是字符串类型。而且,结果的简单枚举应该可能与原始数据表中的列数相匹配。如果没有,请随意将该子句添加到LINQ语句中。
Where c.DataType = GetType(String)
答案 1 :(得分:0)
您还必须翻译这些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()
答案 2 :(得分:0)
非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
答案 3 :(得分:0)
我被迫做了,因为@Putonix说并在数据表上使用循环有两个原因:
1)我无法使用翻译的C#
代码,因为它给了我错误&#34;序列不包含任何元素&#34;即使所有单元格都有值,也因为它似乎只是为字符串字段写的
目前,我的知识还不足以成功编辑此代码,以使其适应我的需求。
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
答案 4 :(得分:0)
发布的自我回答是迭代所有列并将它们视为字符串列,即使它们不是。也就是说,它正在测量和收集不是字符串的.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
更具可读性,但如果你做实际上想要测量非字符串数据,那么在非文本数据上使用它肯定会崩溃。
请注意,循环会跳过非字符串列。要查找715,000行中最长的文本,原始文本大约需要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 ms。扩展方法几乎总是较慢,但这些差异都不值得担心。