2016-07-26 2 views
1

мне нужно знать максимальный ток длину каждого столбца DataTable (с использованием VB.Net)
Мне нужно максимально .ToString.Length для каждого столбца.Max Длина строки в каждом столбце DataTable в VB.Net

Я нашел ниже код С # 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(); 

EDIT
я, наконец, смог перевести код в более читаемый VB. чистый, но не адаптировать его к моим потребностям:

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

Вы должны уметь это перевести, просто набрав те же слова в VB. Для строк новой строки оставьте точку на предыдущей строке. – Plutonix

+1

Вы пробовали использовать онлайн-конвертер C# в VB? –

+0

@Plutonix Я пробовал на одной строке таким образом (но это дает мне ошибки): 'Dim maximumLengthForColumns As List (Of Integer) = Enumerable.Range (0, DT_IntCalc.Columns.Count). Выберите (col> = DT_IntCalc. AsEnumerable(). Выберите (row> = row [col]). OfType (Of String) .Max (Val()> = Val.Length)). ToList() ' – genespos

ответ

0

Опубликованные самостоятельно ответ итерация всех столбцов и обрабатывать их как строки столбцов, даже если они не являются. То есть, он измеряет и собирает длину данных Data12, не являющуюся строкой (что, похоже, не является желательным).

Не связанные струнные datacolumns можно опустить так:

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, хотя если вы do действительно хотите измерить не строковые данные, используя его на нетекстовых данных, обязательно сбой.

Обратите внимание, что цикл пропускает строки, отличные от строки. Чтобы найти самый длинный текст в 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 

Эта форма занимает ~ 12 мс для одних и тех же 715k строк. Методы расширения почти всегда медленнее, но ни одна из этих различий не стоит беспокоиться.

+0

Спасибо за объяснение (я начинаю понимать лямбда-выражения). Я не знаю, из-за моего английского языка, или просто я не смог полностью объяснить то, что искал, но мне нужна именно «ToString.Length». Мне нужна эта длина, потому что мне нужно показать содержимое datatable в «richtextbox», и я подумал об использовании 'String.Format (« {0, Col0Width} {1, Col1Width} ... {n, ColnWidth} », ...)'. Я протестировал опубликованный код на строках без строкой, и он работал без ошибок; почему вы думаете, что он потерпит крах? Есть ли что-то, что я не рассматривал? – genespos

+0

Нет, * your * 'rows (r) (col) .ToString' wont crash, альтернативная версия 'dr.Field (Of T)' будет пытаться использовать 'Of String' в столбце non string. Чтобы получить размер текста всех столбцов в версии linqy (# 2), оставьте строку WHERE DataType и используйте 'm (colName) .ToString(). Length' в цикле. C#, который вы отправили в OP, проверяет только строковые столбцы ('.OfType ()'), и именно это заставило всех поверить, что вы хотели просто проверить длины строк. – Plutonix

0

Вы должны также перевести эти лямбды:

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

A DataTable предоставляет объект Columns, который представляет собой набор определений столбцов. Каждый элемент (который действительно является DataColumn) предоставляет максимально допустимая длина. Выбранный код содержит только данные, хранящиеся в таблице. То есть, он возвращает максимальная используемая максимальная длина по данным, а не максимум, поддерживаемый столбцом.

Чтобы получить максимально допустимую длину, просто просмотрите свойство DataColumns предоставленного объекта DataTable и используйте свойство MaxLength.

Вот фрагмент, используя синтаксис LINQ:

Dim maximumLengthForColumns = From c in dataTable.Columns.Cast(Of DataColumn) 
     Order By c.Ordinal 
     Select c.MaxLength 

Фактический типа это не совсем списка. Это IQueryable(Of Integer). Ycan использовать .ToList(), чтобы заставить перечисление и преобразование вместо того, чтобы позволить ему сидеть без дела, пока вам не понадобится использовать результаты. Вы можете просто оставить IQueryable, если вам просто нужно перечислить результаты, поскольку интерфейс наследует от IEnumerable.

Мне не нужно было включать предложение Order By. Вероятно, это замедлит фактическое выполнение. Но, если в вашей таблице данных есть так много столбцов, что это станет настоящим узким местом, вам нужно будет вернуть его и получить другую рекомендательную инструкцию.

Почему я не добавил пункт фильтрации (Select)? Свойство MaxLength отображается для всех столбцов, а не только для типов строк. И простое перечисление результатов должно, вероятно, соответствовать количеству столбцов в исходной таблице данных. Если нет, не стесняйтесь добавлять предложение в оператор LINQ.

Where c.DataType = GetType(String) 
+0

Спасибо, но мне нужна текущая длина каждого столбца, а не максимально допустимая длина. – genespos

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

+0

Спасибо, но мне нужна текущая длина каждого столбца, а не максимально допустимая длина. – genespos

0

я был вынужден сделать, как @Putonix сказал и использовать петлю над DataTable по двум причинам:

1) Я не смог использовать переведенный код C#, потому что он дает мне ошибку «Последовательность не содержит элементов», даже если все ячейки имеют значение, а также потому, что они, похоже, записаны только для строковых полей.
На данный момент моих знаний недостаточно, чтобы успешно редактировать этот код, чтобы адаптировать его к моим потребностям.

2) 2 ответа, которые предлагают использовать MaxLength, не дают мне то, что мне нужно, потому что мне нужна текущая длина каждого столбца, а не максимально допустимая длина.

Спасибо всем за помощь

Так вот код, который я использовал:

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 
Смежные вопросы