使用LINQ C#</fileinfo>比较List <fileinfo>中的文件

时间:2014-09-30 23:18:30

标签: c# linq list file compare

我有2个文件集合List<FileInfo>。我目前正在使用2 x foreach遍历每个集合并匹配文件(如下所示)。是否有更快的方法在LINQ和.RemoveAt找到时执行此操作。

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

            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;
                }
            }
    

干杯。

3 个答案:

答案 0 :(得分:5)

您可以使用Enumerable.Except<TSource>方法:

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();

在上面的示例中,您可以获得sFiles中不存在的dFiles中的所有文件。

答案 1 :(得分:1)

对于一个,如果执行此代码将抛出异常,因为您在迭代它时修改枚举(dFiles)。但是,使用ToList() method可以轻松解决这个问题,以便复制枚举。这也会产生一个问题,因为无论删除都会增加索引,这也会导致错误 - 口语异常异常。

如果你担心速度,那就不要了。 Linq使用使用foreach和yield返回的方法,并且在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));

答案 2 :(得分:1)

如果你想换空间一段时间,你可以建立一个列表的哈希集,并在哈希集中查找另一个列表的每个元素。查找是O(1),而循环是O(n)