作者热门文章
- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个简单的方法来将 FileInfo 对象数组与文件名列表进行比较,以检查哪些文件已经被处理过。然后返回未处理的列表。
此方法的循环迭代了大约 250,000 个 FileInfo 对象。这花费了大量的时间来竞争。
效率低下显然是对 processedFiles 集合的 Contains 方法调用。
首先,我如何检查以确保我对原因的怀疑是真实的,其次,我如何改进方法以加快该过程?
public static List<FileInfo> GetUnprocessedFiles(FileInfo[] allFiles, List<string> processedFiles)
{
List<FileInfo> unprocessedFiles = new List<FileInfo>();
foreach (FileInfo fileInfo in allFiles)
{
if (!processedFiles.Contains(fileInfo.Name))
{
unprocessedFiles.Add(fileInfo);
}
}
return unprocessedFiles;
}
最佳答案
A List<T>
的 Contains
方法以线性时间运行,因为它可能必须枚举整个列表以证明项目的存在/不存在。我建议你使用 HashSet<string>
或类似的代替。 HashSet<T>
的 Contains
方法旨在以常量 O(1)
运行时间,即它不应该取决于集合中的项目数量。
这个小改动应该可以使整个方法在线性时间内运行:
public static List<FileInfo> GetUnprocessedFiles(FileInfo[] allFiles,
List<string> processedFiles)
{
List<FileInfo> unprocessedFiles = new List<FileInfo>();
HashSet<string> processedFileSet = new HashSet<string>(processedFiles);
foreach (FileInfo fileInfo in allFiles)
{
if (!processedFileSet.Contains(fileInfo.Name))
{
unprocessedFiles.Add(fileInfo);
}
}
return unprocessedFiles;
}
如果可能的话,我会建议 3 项改进:
ISet<T>
作为参数。这样,您就不必每次都重建集合。string
和FileInfo
)的不同表示。选择一个并使用它。HashSet<T>.ExceptWith
方法而不是自己做循环。请记住,这会改变集合。如果您可以使用 LINQ,并且可以负担得起在每次调用时建立一个集合,那么还有另一种方法:
public static IEnumerable<string> GetUnprocessedFiles
(IEnumerable<string> allFiles, IEnumerable<string> processedFiles)
{
// null-checks here
return allFiles.Except(processedFiles);
}
关于c# - 我有一个性能不佳的方法,我该如何提高它的效率?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4096679/
我是一名优秀的程序员,十分优秀!