You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用单LINQ查询或更优方式获取新旧文件及旧文件计数

问题描述

现有方法用于返回X天以内的IEnumerable<ZipArchiveEntry>:

private static IEnumerable<ZipArchiveEntry> GetFiles(ZipArchive archive, int days)
{
    return archive.Entries
        .Where(y => y.LastWriteTime > DateTime.Now.AddDays(-days))
        .OrderBy(x => x.LastWriteTime);
}

需求变更:需要在单个方法中同时返回X天以内的文件集合和X天以上的文件计数。

已尝试的写法如下,询问是否可以通过单个LINQ的Where查询实现:

private static (IEnumerable<ZipArchiveEntry>, int count) GetFiles(ZipArchive archive, int days)
{
    var entries = archive.Entries
        .Where(y => y.LastWriteTime > DateTime.Now.AddDays(-days))
        .OrderBy(x => x.LastWriteTime);

    var count = archive.Entries
        .Where(y => y.LastWriteTime < DateTime.Now.AddDays(-days))
        .OrderBy(x => x.LastWriteTime).ToList().Count;

    return (entries, count);
}
优化方案

现有写法的问题

  1. 两次遍历archive.Entries,条目数量较大时会浪费性能;
  2. 计数时的OrderBy和ToList完全多余:排序不影响计数结果,直接调用Count()即可,无需转成List;
  3. 重复计算DateTime.Now.AddDays(-days),可能导致两次判断的截止日期存在细微时间差。

最优实现(单次遍历+LINQ)

可以通过GroupBy实现单次遍历分组,同时获取符合条件的集合和不符合条件的计数,避免重复遍历:

private static (IEnumerable<ZipArchiveEntry> RecentEntries, int OlderCount) GetFiles(ZipArchive archive, int days)
{
    // 提前计算截止日期,避免重复计算和时间偏差
    var cutoffDate = DateTime.Now.AddDays(-days);
    
    // 单次遍历,按是否符合X天内条件分组
    var groupedEntries = archive.Entries.GroupBy(entry => entry.LastWriteTime > cutoffDate);
    
    // 获取X天内的文件并按写入时间排序
    var recentEntries = groupedEntries.FirstOrDefault(g => g.Key)?.OrderBy(entry => entry.LastWriteTime) 
                        ?? Enumerable.Empty<ZipArchiveEntry>();
    
    // 获取X天以上的文件计数
    var olderCount = groupedEntries.FirstOrDefault(g => !g.Key)?.Count() ?? 0;
    
    return (recentEntries, olderCount);
}

更高效的手动遍历实现

如果追求极致性能,手动遍历一次条目并分类统计,避免LINQ分组的额外开销:

private static (IEnumerable<ZipArchiveEntry> RecentEntries, int OlderCount) GetFiles(ZipArchive archive, int days)
{
    var cutoffDate = DateTime.Now.AddDays(-days);
    var recentEntries = new List<ZipArchiveEntry>();
    int olderCount = 0;
    
    foreach (var entry in archive.Entries)
    {
        if (entry.LastWriteTime > cutoffDate)
        {
            recentEntries.Add(entry);
        }
        else
        {
            olderCount++;
        }
    }
    
    // 对X天内的文件按写入时间排序
    recentEntries.Sort((a, b) => a.LastWriteTime.CompareTo(b.LastWriteTime));
    
    return (recentEntries, olderCount);
}

关于“单个Where查询实现”的说明

单个Where无法同时完成筛选和计数两个目标,因为Where只负责筛选出符合条件的元素。但可以通过上述单次遍历的方式,用一次LINQ操作(GroupBy)或手动遍历替代两次Where查询,达到最优性能。

内容的提问来源于stack exchange,提问作者user584018

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 15:55:26