如何根据名称比较两个不同文件的文件夹?

时间:2010-12-07 13:11:19

标签: c# linq

我有两个文件夹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;

有什么建议吗?

3 个答案:

答案 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));