2014-09-30 106 views
0

我有2個文件集合作爲List<FileInfo>。我目前使用2 x foreach來遍歷每個集合並匹配文件(如下所示)。有沒有更快的方法在LINQ和.RemoveAt這樣做,當發現。使用LINQ列表<FileInfo>比較文件使用LINQ C#

  • 我需要文件名和文件長度匹配。

     var sdinfo = new DirectoryInfo(srcPath); 
         var ddinfo = new DirectoryInfo(dstPath); 
    
         var sFiles = new List<FileInfo>(sdinfo.GetFiles("*", SearchOption.AllDirectories)); 
         var dFiles = new List<FileInfo>(ddinfo.GetFiles("*", SearchOption.AllDirectories)); 
    
         foreach (var sFile in sFiles) 
         { 
          bool foundFile = false; 
          int i = 0; 
    
          foreach (var dFile in dFiles) 
          { 
           if (sFile.Name == dFile.Name && sFile.Length == dFile.Length) 
           { 
            foundFile = true; 
            dFiles.RemoveAt(i); 
           } 
           i += 1; 
          } 
         } 
    

乾杯。以上你從sFiles是在dFiles缺席所有文件

private class FileInfoComparer : IEqualityComparer<FileInfo> 
{ 
    public bool Equals(FileInfo x, FileInfo y) 
    { 
     return x == null ? y == null : (x.Name.Equals(y.Name, StringComparison.CurrentCultureIgnoreCase) && x.Length == y.Length); 
    } 

    public int GetHashCode(FileInfo obj) 
    { 
     return obj.GetHashCode(); 
    } 
} 

sFiles = sFiles.Except(dFiles, new FileInfoComparer()).ToList(); 

在這個例子中:

+1

我假設您的示例代碼中存在拼寫錯誤。 sdinfo和ddinfo都使用srcPath。見行1和2 – 2014-09-30 23:28:09

+0

是的,這是一個O型。好地方,歡呼聲。編輯。 – 2014-10-01 00:29:19

回答

5

你可以使用Enumerable.Except<TSource>方法。

+0

OP要求提供兩個for循環的更快解決方案。 LINQ對Except()有不同的算法嗎?我意識到它是更少的代碼行。我很好奇表現。 – 2014-09-30 23:30:46

+0

@ KC-NH'Except'方法使用'Set'類(散列集的內部實現):[LINQ source](http://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable。 CS#e289e6c98881b2b8#參考)。 – Dmitry 2014-09-30 23:48:31

1

其中之一,如果執行此代碼將拋出一個異常,因爲您在迭代時修改枚舉(dFiles)。但是,使用ToList() method可以輕鬆解決此問題,以便複製枚舉。這也會遇到問題,因爲無論刪除操作如何,您的索引都會增加,這也會導致錯誤 - 通俗的異常情況。

如果你擔心速度,不要這樣。 Linq使用使用foreach和收益率回報的方法,並且在Reference Source的源中大多可見。

如果您想讓代碼更易於閱讀,那麼這就是Linq變得有用的地方。其一,有.Join() Method

foreach(var fileToRemove in sFiles.Join(dFiles, s => s, d => d, (s, d) => s).ToArray()) 
    dFiles.Remove(fileToRemove); 

假設你通過DLIST迭代之後,你還可以使用.Except(...) Method

var files = sdinfo.GetFiles("*", SearchOption.AllDirectories) 
    .Except(ddinfo.GetFiles("*", SearchOption.AllDirectories)); 

最後,如果你需要保持sFiles,下面的代碼包裝它們都在一起

List<string> sFiles, dFiles; 
dFiles = ddinfo.GetFiles("*", SearchOption.AllDirectories) 
    .Except(sFiles = sdinfo.GetFiles("*", SearchOption.AllDirectories)); 
+0

這看起來很有用。基本上,如果有一個不匹配或缺少,我在方法上返回false。 – 2014-10-01 00:28:23

1

如果你想交換空間的時間,哈希集。查找是O(1),而循環是O(n)