使用C#中的LINQ中的Intersect方法

4

我正在尝试使用Intersect方法从两个文件夹中获取相同的文件。 所有文件夹中的123.xml文件(内容、日期、大小)均未发生更改。

Scores\Content\123.xml
Scores\Content\hi.xml
Scores\123.xml

Power\Content\123.xml
Power\Content\helo.xml
Power\123.xml

这是来自C#代码

        System.IO.DirectoryInfo dir1 = new System.IO.DirectoryInfo(path1);
        System.IO.DirectoryInfo dir2 = new System.IO.DirectoryInfo(path2);

        IEnumerable<System.IO.FileInfo> list1 = dir1.GetFiles("*.*", System.IO.SearchOption.AllDirectories);
        IEnumerable<System.IO.FileInfo> list2 = dir2.GetFiles("*.*", System.IO.SearchOption.AllDirectories);

        FileCompare myFileCompare = new FileCompare();

        bool areIdentical = list1.SequenceEqual(list2, myFileCompare);

        if (areIdentical == true)
        {
            Console.WriteLine("the two folders are the same");
        }
        else
        {
            Console.WriteLine("The two folders are not the same");
        }


        var queryCommonFiles = list1.Intersect(list2, myFileCompare);

queryCommonFiles只返回Content文件夹中的123.xml,而不是其他文件。

这是FileCompare中的代码:

class FileCompare : System.Collections.Generic.IEqualityComparer<System.IO.FileInfo>
{

    public FileCompare() { }

    public bool Equals(System.IO.FileInfo f1, System.IO.FileInfo f2)
    {
        return (f1.Name == f2.Name &&
                f1.Length == f2.Length);
    }

    // Return a hash that reflects the comparison criteria. According to the 
    // rules for IEqualityComparer<T>, if Equals is true, then the hash codes must
    // also be equal. Because equality as defined here is a simple value equality, not
    // reference identity, it is possible that two or more objects will produce the same
    // hash code.
    public int GetHashCode(System.IO.FileInfo fi)
    {
        string s = String.Format("{0}{1}", fi.Name, fi.Length);
        return s.GetHashCode();
    }

}

编辑:

var queryList1Only = (from file in list1
                                  select file).Except(list2, myFileCompare);

            Console.WriteLine("The following files are in list1 but not list2:\n");
            foreach (var v in queryList1Only)
            {
                Console.WriteLine(v.FullName);
            }


            var queryList2Only = (from file in list2
                                  select file).Except(list1, myFileCompare);

            Console.WriteLine("The following files are in list2 but not list1:\n");
            foreach (var v in queryList2Only)
            {
                Console.WriteLine(v.FullName);
            }

这将产生list1的hi.xml和list2的helo.xml。就像我说的,intersect方法只会产生一个123.xml。

如果有任何建议,欢迎提出。

谢谢。


这是因为“list1.Intersect”实际上只比较文件名而不是带有文件夹结构的文件名吗? - superstar
我建议您在Equals和GetHashCode方法中加入一些诊断信息... 我预计其他文件的长度可能不同,或者类似于那样的情况。 - Jon Skeet
2
@superstar,FileInfo中的Name属性不包含路径。 - Adriano Carneiro
@Adrian:我看到了,因为得分和能力的文件夹结构不同,所以我不能在那里使用FullName。 - superstar
如果我有两个不同长度或任何差异的123.xml文件,在比较中(在编辑下)应该将它们列出,但是我只得到了list1中的hi.xml和list2中的helo.xml作为差异。 - superstar
@Adrian:你的评论帮助我去查看了它。谢谢。 - superstar
3个回答

3

我刚刚修改了Equals方法以实现所需的结果。

class FileCompare : System.Collections.Generic.IEqualityComparer<System.IO.FileInfo>
    {

        public FileCompare() { }

        public bool Equals(System.IO.FileInfo f1, System.IO.FileInfo f2)
        {
            return (f1.Name == f2.Name && f1.Directory.Name == f2.Directory.Name && 
                    f1.Length == f2.Length);
        }

        // Return a hash that reflects the comparison criteria. According to the 
        // rules for IEqualityComparer<T>, if Equals is true, then the hash codes must
        // also be equal. Because equality as defined here is a simple value equality, not
        // reference identity, it is possible that two or more objects will produce the same
        // hash code.
        public int GetHashCode(System.IO.FileInfo fi)
        {
            string s = String.Format("{0}{1}", fi.Name, fi.Length);
            return s.GetHashCode();
        }

    }

2

一切看起来都很好。请确保Scores\123.xmlPower\123.xml长度相同。


它们具有相同的长度、日期和内容。(我只是将同一个文件复制到这两个文件夹中) - superstar

2
因为您只是使用FileInfo.Name和FileInfo.Length进行比较,所以Content\123.xml与123.xml相同(假设这两个文件的大小相同,我猜测这是您的测试数据的情况)。
因此,就您的FileCompare类而言,您的输入集合包含重复项。根据MSDN的说法,Intersect评估每个集合中的不同元素。

是的,Intersect评估不同的元素。 - superstar
因此,[123.xml, hi.xml, 123.xml] 和 [123.xml, helo.xml, 123.xml] 的不同元素为 [123.xml, hi.xml] 和 [123.xml, helo.xml]。它们的交集是单个元素 123.xml。 - Alex Peck
但是我需要识别相同的文件,所以我修改了Equals方法来处理它。 - superstar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接