我有两个文件夹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;
有什么建议吗?
答案 0 :(得分:9)
嗯,一方面这种方法非常低效 - 每次开始使用新的dir2.GetFiles
时都会调用f1
。然后,它将为每个与{em>当前 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
所以结果将是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);
现在 应该更有效...
编辑:我假设你想要A中的文件而不是B中的文件,基于可能是问题的早期版本。 (我不确定它是否在前五分钟内被编辑。显然当前的代码不会返回B中的任何内容而不是A..
如果您想要对称差异,请使用HashSet<T>.SymmetricExceptWith
:
var inExactlyOneDirectory = new HashSet<string>(dir1Files);
inExactlyOneDirectory.SymmetricExceptWith(dir2Files);
(请注意,我不喜欢这样一个事实:SymmetricExceptWith
是一个改变现有集合的void方法,而不是返回一个新集合或只是一个序列。除了其他任何东西,它意味着变量名称只是合适的在第二个陈述之后,而不是第一个陈述。)
编辑:如果您需要名称和大小的唯一性,您真的需要一个代表两者的匿名类型。不幸的是,很难根据它创建HashSet<T>
。所以你需要一个像这样的扩展方法:
public static HashSet<T> ToHashSet<T>(this IEnumerable<T> set)
{
return new HashSet<T>(set);
}
然后:
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);
答案 1 :(得分:2)
Jon Skeet的回答应该可以帮助您理解为什么您当前的解决方案不起作用,并且从根本上说效率低下。
至于解决问题,一个选项是使用HashSet.SymmetricExceptWith
方法,该方法“修改当前的HashSet(Of T)对象,仅包含该对象或指定集合中存在的元素,但不是两个。“
// Thanks to Jon Skeet for template
var dir1Files = dir1.GetFiles("*", SearchOption.AllDirectories)
.Select(x => x.Name);
var dir2Files = dir2.GetFiles("*", SearchOption.AllDirectories)
.Select(x => x.Name);
var filesNotInBoth = new HashSet<string>(dir1Files);
filesNotInBoth.SymmetricExceptWith(dir2Files);
答案 2 :(得分:-1)
var files2 = dir2.GetFiles("*", SearchOption.AllDirectories);
var filesnotinboth = dir1.GetFiles("*", SearchOption.AllDirectories)
.Where(f1 => !files2.Any(f2 => f2.Name == f1.Name));