gpt4 book ai didi

c# - 在 C# : Leveraging LINQ. AsParallel 中列出文件夹内的重复文件

转载 作者:行者123 更新时间:2023-11-30 15:37:17 29 4
gpt4 key购买 nike

我已将以下算法写入 C# 代码以递归列出文件夹中的文件。

  1. 开始遍历目录及其子目录中的文件列表目录。
  2. 在列表中存储文件名和路径。
  3. 如果当前文件匹配列表中的任何其他文件,则将两个文件标记为重复。
  4. 从列表中获取所有标记为重复的文件。
  5. 按名称分组并返回。

在包含 50,000 个文件和 12,000 个子目录的文件夹上执行速度非常慢。由于磁盘读取操作基本上是耗时的任务。即使 LINQ.Parallel() 也无济于事。

实现:

class FileTuple
{
public string FileName { set; get; }
public string ContainingFolder { set; get; }
public bool HasDuplicate { set; get; }
public override bool Equals(object obj)
{
if (this.FileName == (obj as FileTuple).FileName)
return true;
return false;
}
}
  1. FileTuple 类跟踪文件名和包含目录,标志跟踪重复状态。
  2. 我重写了 equals 方法来只比较文件名,在fileTuples 的集合。

以下方法查找重复文件并作为列表返回。

    private List<FileTuple> FindDuplicates()
{
List<FileTuple> fileTuples = new List<FileTuple>();
//Read all files from the given path
List<string> enumeratedFiles = Directory.EnumerateFiles(txtFolderPath.Text, "*.*", SearchOption.AllDirectories).Where(str => str.Contains(".exe") || str.Contains(".zip")).AsParallel().ToList();
foreach (string filePath in enumeratedFiles)
{
var name = Path.GetFileName(filePath);
var folder = Path.GetDirectoryName(filePath);
var currentFile = new FileTuple { FileName = name, ContainingFolder = folder, HasDuplicate = false, };

int foundIndex = fileTuples.IndexOf(currentFile);
//mark both files as duplicate, if found in list
//assuming only two duplicate file
if (foundIndex != -1)
{
currentFile.HasDuplicate = true;
fileTuples[foundIndex].HasDuplicate = true;
}
//keep of track of the file navigated
fileTuples.Add(currentFile);
}

List<FileTuple> duplicateFiles = fileTuples.Where(fileTuple => fileTuple.HasDuplicate).Select(fileTuple => fileTuple).OrderBy(fileTuple => fileTuple.FileName).AsParallel().ToList();
return duplicateFiles;
}

能否请您提出一种提高性能的方法。

感谢您的帮助。

最佳答案

Can you please suggest a way to improve the performance.

一个明显的改进是使用 Dictionary<FileTuple, FileTuple>以及 List<FileTuple> .这样你就不会有 O(N) IndexOf对每张支票进行操作。请注意,您还需要覆盖 GetHashCode() - 你应该已经有关于此的警告。

不过我怀疑它会产生很大的不同 - 我希望这主要是 IO 绑定(bind)的。

此外,我怀疑最后的过滤和排序会成为一个重大瓶颈,所以使用 AsParallel在最后一步不太可能做太多。当然,您应该衡量所有这些。

最后,整个方法可以变得更简单,甚至不需要 HasDuplicate标志或任何覆盖 Equals/GetHashCode :

private List<FileTuple> FindDuplicates()
{
return Directory.EnumerateFiles(txtFolderPath.Text, "*.*",
SearchOption.AllDirectories)
.Where(str => str.Contains(".exe") ||
str.Contains(".zip")
.Select(str => new FileTuple {
FileName = Path.GetFileName(str),
ContainingFolder = Path.GetDirectoryName(str))
})
.GroupBy(tuple => tuple.FileName)
.Where(g => g.Count() > 1) // Only keep duplicates
.OrderBy(g => g.Key) // Order by filename
.SelectMany(g => g) // Flatten groups
.ToList();
}

关于c# - 在 C# : Leveraging LINQ. AsParallel 中列出文件夹内的重复文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12763797/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com