我有两个文件夹A和B ..Inside有多个文件在那里,B里面有多个文件.我必须检查A中的文件,B中的文件用于非相同的文件...我试过这样,它给了整个搜索结果...
var filesnotinboth = from f1 in dir1.GetFiles("*", SearchOption.AllDirectories)
from f2 in dir2.GetFiles("*",SearchOption.AllDirectories)
where f1.Name != f2.Name
select f1.Name;
Run Code Online (Sandbox Code Playgroud)
有什么建议吗?
好吧,一方面这种方法效率非常低 - dir2.GetFiles每次开始使用新方法时都会调用f1.然后它将为每个f2与当前 不匹配的匹配f1.因此,即使它将在以后 匹配f1,它仍然会输出.想象一下,dir1包含A,B和C,而dir2包含C和D.你最终会这样:
f1 f2 Result of where?
A C True
A D True
B C True
B D True
C C False
C D True
Run Code Online (Sandbox Code Playgroud)
所以结果将是A,A,B,B,C - 你仍然有 C(你不想要的) - 只是不像A和B那样频繁.
您想要使用set操作,如下所示:
var dir1Files = dir1.GetFiles("*", SearchOption.AllDirectories)
.Select(x => x.Name);
var dir2Files = dir2.GetFiles("*", SearchOption.AllDirectories)
.Select(x => x.Name);
var onlyIn1 = dir1Files.Except(dir2Files);
Run Code Online (Sandbox Code Playgroud)
现在应该工作,更有效率......
编辑:我假设您希望文件在A但不在B中,基于可能的早期版本的问题.(我不确定它是否在前五分钟内被编辑过.显然当前的代码不会返回B中的任何内容而不是A.)
如果您想要对称差异,请使用HashSet<T>.SymmetricExceptWith:
var inExactlyOneDirectory = new HashSet<string>(dir1Files);
inExactlyOneDirectory.SymmetricExceptWith(dir2Files);
Run Code Online (Sandbox Code Playgroud)
(注意,我不喜欢这样SymmetricExceptWith一个事实,即一个改变现有集合的void方法,而不是返回一个新集合或只是一个序列.除了其他任何东西,它意味着变量名称仅适用于第二个语句之后,而不是第一个.)
编辑:如果您需要名称和大小的唯一性,您真的需要一个代表两者的匿名类型.不幸的是,HashSet<T>基于它创建一个很难.所以你需要一个像这样的扩展方法:
public static HashSet<T> ToHashSet<T>(this IEnumerable<T> set)
{
return new HashSet<T>(set);
}
Run Code Online (Sandbox Code Playgroud)
然后:
var dir1Files = dir1.GetFiles("*", SearchOption.AllDirectories)
.Select(x => new { x.Name, x.Length });
var dir2Files = dir2.GetFiles("*", SearchOption.AllDirectories)
.Select(x => new { x.Name, x.Length });
var difference = dir1Files.ToHashSet();
difference.SymmetricExceptWith(dir2Files);
Run Code Online (Sandbox Code Playgroud)