我有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;
}
}
干杯。
答案 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)