我可以使用什么模式来确保我不会执行两次相同的操作

时间:2013-05-12 06:54:28

标签: c# design-patterns

我的程序正在寻找重复项目。它将文件与文件夹和子文件夹中的每个其他文件进行比较。问题是,它正在重复检查。

例如,请考虑以下(粗略)文件夹结构

-Folder1
---文件1
---文件2
--- File3

-Folder2
---文件1
--- File2

-Folder3
---文件1
---文件2
---文件3
--- FILE4

因此,为了确保清晰,它意味着文件夹1,文件夹2和文件夹3都在根级别,每个文件夹中都包含每个文件夹中的文件。

我的程序遍历,通过2个foreach循环将每个程序进行比较。

 foreach (string path01 in  Directory.GetFiles(SourcePath, "*.*", SearchOption.AllDirectories))
 {
     foreach (string path02 in  Directory.GetFiles(SourcePath, "*.*", SearchOption.AllDirectories))
     {
           //perform logic with path01 and path02
     }
 }

现在,问题是其中一个迭代会比较Folder1 \ File1和Folder2 \ File1(这是期望的),但它也会将Folder2 \ File1与Folder1 \ File1进行比较。由于检查已经完成,因此效率很低。现在我承认,只有我上面列出的文件/文件夹可以说是谁在乎,但我的应用程序正在比较数千个文件夹,我不知道有多少文件。

在我的脑海中,我想我必须按字母顺序排序,然后使用for循环并始终在下一次迭代开始,以防止搜索向后但我不确定。有一次,我认为冒泡排序可能有所帮助,但这不是关于排序,尽管我可以或不可以使用它。

我确信此类问题已记录并存在,我遇到的问题是,(正如您可以通过我的帖子的长度来判断)如何在Google搜索中进行描述,以便我可以研究是否有模式存在。

所以,我的问题是,这种问题的模式或范例是否已存在?

2 个答案:

答案 0 :(得分:2)

你是如何检测重复的?您只是在寻找重复的文件名,还是打开文件并阅读内容?无论哪种方式,您都应该使用HashSet

var visitedFiles = new HashSet<String>();

foreach (string path01 in  Directory.GetFiles(SourcePath, "*.*", SearchOption.AllDirectories)) {
   String contents = // read in file contents
   String contentHash = md5(contents); // do a md5 hash of the contents

   if (!visitedFiles.contains(contentHash)) {
       visitedFiles.add(contentHash);
   } else {
      // duplicate file found
   }
}

这是一个未经测试的基本示例。您可以根据需要对其进行修改。您可以存储一个包含更多信息的类对象(根据您的需要对其进行自定义),而不是将Strings存储在hashset中。

无论如何,此解决方案的时间复杂度为O(n),与O(n^2)的时间复杂度相反。

答案 1 :(得分:1)

var files = Directory.GetFiles(SourcePath, "*.*", SearchOption.AllDirectories);
for (int i = 0; i < files.Length-1; i++)
    for (int j = i+1; j < files.Length; j++)
    {
        string path1 = files[i];
        string path2 = files[j];
        //perform logic with path1 and path2          
    }

此代码在两个方面比您的代码表现更好:

  1. 对于您而言,它不会将每对文件进行两次比较。
  2. 仅拨打Directory.GetFile一次。