#c# #linq
#c# #linq
Вопрос:
У меня есть папка с 198 файлами, среди них 25 файлов с датой последней записи 22.06.2014. Я пытаюсь получить этот набор последних измененных файлов, используя следующий код:
public static IEnumerable<FileInfo> GetLatestFiles(string path)
{
return new DirectoryInfo(path)
.GetFiles("*.log")
.GroupBy(f => f.Extension)
.Select(g => g.OrderByDescending(f => f.LastWriteTime
.Date
.ToShortDateString())
.First());
}
Однако он возвращает мне только один файл, потому что он также проверяет последнее изменение времени, несмотря на то, что я обрезал дату. Есть ли какой-либо подход для перечисления этого списка файлов без учета времени?
Комментарии:
1. Просто
First()
выньте.2. Вы используете
First()
?3. Зачем вы используете
GroupBy ... Extension
, если вы уже отфильтровали все, кроме*.log
файлов?4. Действительно, это все перепутано. Вы действительно пытаетесь получить все файлы журналов, которые имеют самую последнюю дату последнего изменения?
5. если я
First()
вынимаю, он начинает жаловаться на неправильное приведение типов. Если конец моего кода выглядит так.Select(g => g.OrderByDescending(f => f.LastWriteTime.Date.ToShortDateString())) as IEnumerable<FileInfo>;
, он возвращает мне null 🙂
Ответ №1:
Легче определить, что вы делаете, если вы не просто выравниваете по точкам, а по вызовам верхнего уровня:
public static IEnumerable<FileInfo> GetLatestFiles(string path)
{
return new DirectoryInfo(path)
.GetFiles("*.log")
.GroupBy(f => f.Extension)
.Select(g => g.OrderByDescending(f => f.LastWriteTime
.Date
.ToShortDateString())
.First());
}
Теперь более очевидно, что вы выполняете упорядочение на основе строк. Если вы не находитесь в культуре, которая сначала ставит год, затем месяц, затем день, это почти наверняка не то, что вы хотите. Вероятно, вас вообще не волнует строковое представление. Всегда избегайте преобразования в строку, если вы действительно не заинтересованы в текстовом представлении.
Далее вы делаете пару странных вещей:
- Вы извлекаете только файлы «* .log», но группируете по расширению
- Вы получаете только самый первый результат каждой группы после упорядочивания
Я подозреваю, что вы действительно хотите сгруппировать по дате и вернуть все в самую последнюю группу. Например:
public static IEnumerable<FileInfo> GetLatestFiles(string path)
{
return new DirectoryInfo(path)
.GetFiles("*.log")
.GroupBy(f => f.LastWriteTime.Date)
.OrderByDescending(g => g.Key) // Order the groups by date (desc)
.First(); // Just return the most recent group
}
(Обратите внимание, что это приведет к сбою, если в каталоге нет файлов… что вы хотите, чтобы это делало в этом случае?)
Вы также должны учитывать, какой часовой пояс вас интересует — два файла могут иметь одинаковую дату последнего изменения в одном часовом поясе, но не в другом…
Комментарии:
1. Это то, чего я действительно хотел! Большое спасибо. Остальная часть проблем, таких как пустая папка или часовой пояс, уже решена 🙂
Ответ №2:
Использование First()
в конце разумно, чтобы вы получили только один файл. Если вы удалите его, все файлы будут упорядочены, как вы уже сделали.
Однако, используя уже созданный вами запрос, вы не получите то, что хотите. Вместо этого вы можете попробовать что-то вроде следующего:
DirectoryInfo(path).GetFiles("*.log")
.Where(x=>x.LastWriteTime.ToShortDateString()=="06/22/2014");
Комментарии:
1. если я
First()
вынимаю, он начинает жаловаться на неправильное приведение типов. Если конец моего кода выглядит так.Select(g => g.OrderByDescending(f => f.LastWriteTime.Date.ToShortDateString())) as IEnumerable<FileInfo>;
, он возвращает мне значение null.2. @TrevorPhilips пожалуйста, попробуйте код, который я опубликовал. Насколько я понимаю, код, который у вас есть, и который вы хотите получить, не согласуется. Пожалуйста, дайте мне знать о вашей попытке. Спасибо
Ответ №3:
Попробуйте снять First()
:
public static IEnumerable<FileInfo> GetLatestFiles(string path)
{
return new DirectoryInfo(path)
.GetFiles("*.log")
.GroupBy(f => f.Extension)
.Select(g => g.OrderByDescending(f => f.LastWriteTime
.Date
.ToShortDateString()));
}