2014-09-30 108 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)