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()

VB.Net中数据表的每列中的最大字符串长度

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