Sonhospa Ответов: 2

Как получить только определенные столбцы в этом выражении LINQ?


Всем привет,

Я использую запрос LINQ из другого обсуждения на форуме и смог адаптировать его так, чтобы он работал и даже сообщал об активности в пользовательском интерфейсе (см. код ниже). Результатом запроса является BindingList(of FileInfo), который я затем использую в качестве источника данных "FilesBindingSource" для подачи DataGridView.

Теперь я хотел бы получить / отобразить только часть информации (имя файла + длина + LastWriteTime), и я прочитал, что хочу поставить еще один "Select" после предложения Where -... но я весь день боролся с синтаксисом.

Не мог бы кто-нибудь помочь мне с правильным синтаксисом?

Большое спасибо,
С уважением
Майкл

Что я уже пробовал:

For Each result As FileInfo In dirInfo.GetFiles(pattern).Select(Function(file) file).Where(Function(s)
       supportedExtensions.Contains(Path.GetExtension(s.Extension).ToLower()))
				queue.Enqueue(result)
				report(dirInfo.FullName)
Next result
Task.WaitAll(dirInfo.GetDirectories().Select(
               Function(d) Task.Factory.StartNew(
			   Sub() InternalCollectFiles(d, pattern, queue))).ToArray())

2 Ответов

Рейтинг:
18

Graeme_Grant

Вот Linq, необходимый для того, чтобы делать то, что вы хотите:

Dim results = dirinfo.GetFiles(pattern)
    .Where(Function(x) supportedExtensions.Contains(x.Extension.ToLower()))
    .Select(Function(x) New With {
        .Name = x.Name,
        .Length = x.Length,
        .LastWriteTime = x.LastWriteTime
    })

Чтобы помочь объяснить оператор Linq, за вычетом выбора выходных данных, вот версия без Linq:
Dim dirinfo = New DirectoryInfo(dirPath)
Dim files = dirinfo.GetFiles(pattern)

For Each fileInfo In files

    If supportedExtensions.Contains(fileInfo.Extension) Then
        queue.Enqueue(fileInfo)
    End If
Next


Maciej Los

5ed!
Ты был быстрее меня, потому что у меня был спор с ОПОМ по другому вопросу.

Sonhospa

Хотя спасибо, поскольку с точки зрения "ученика" я понимаю больше из ваших дополнительных объяснений. Я также ценю вашу очень хорошую (!) идею вернуть определенный тип.

Graeme_Grant

Обновил свое решение с помощью версии, отличной от Linq...

Sonhospa

Хорошо, что вы пишете, теперь у меня есть кнопка "ответить", так что я тоже могу поблагодарить вас :-) и извиниться за то, что не привык (а также не доволен) измененным пользовательским интерфейсом.

Спасибо Вам также за обновление / non-Linq версии! Очевидно, что это очень крутой и краткий способ достичь той же цели без всех синтаксических хлопот, которые я безуспешно пытался освоить. И в моем обучении различные способы, которыми идут профессионалы, чрезвычайно интересны для меня!

Как вы думаете, версия LINQ предпочтительнее для скорости или sth еще, или это просто вопрос вкуса?

Graeme_Grant

Не проблема.

Вышеприведенная версия Linq является отложенным исполнением, поэтому код запускается только при повторении результатов. Чтобы заставить его немедленно выполнить, используйте .ToList() Очень мощный и гибкий при правильном использовании...

Рейтинг:
10

Maciej Los

Это очень просто. Видеть:

Dim dirinfo As DirectoryInfo = New DirectoryInfo("C:\users\Sonhospa\documents") 'change path to your needs
Dim pattern As String = "*"
Dim supportedExtensions As String() = {".xls", ".doc", ".xlsx", ".docx"}

Dim filelist = dirInfo.GetFiles(pattern) _
    .Where(Function(file) supportedExtensions.Contains(Path.GetExtension(file.Extension).ToLower())) _
    .Select(Function(file) New With _
    { _
        .FileName = file.FullName, _
        .Length = file.Length, _
        .LastWriteTime = file.LastWriteTime _
    }) _
    .ToList()


Примечание № 1: я переехал Where заявление вверх, до того, как Select
Примечание № 2: возвращает код List(of AnonymousType(Of String, Int64, DateTime))

Если вы хотите вернуть коллекцию определенного типа, Пожалуйста, смотрите раздел: Как вернуть результат запроса LINQ в виде определенного типа (Visual Basic) | Microsoft Docs[^]

Например:
Public Class ShortFileInfo

	Public Property FileName As String
	Public Property Length As Long
	Public Property LastWriteTime As DateTime
	
End Class


Запрос должен быть изменен таким образом:
.Select(Function(file) New ShortFileInfo() With _
{ _
    .FileName = file.FullName, _
    .Length = file.Length, _
    .LastWriteTime = file.LastWriteTime _
}) _


Sonhospa

Еще раз спасибо, Мацей. Я думаю, что попробую этот способ с дополнительным классом 'ShortFileInfo', так как с анонимным типом я получаю ошибку (не могу преобразовать в FileInfo).

Кстати, ваше дополнительное объяснение мне очень помогло!

Maciej Los

Всегда пожалуйста.
Я рад, что могу помочь.
Овации
Мацей