C# 如何在忽略文件扩展名的情况下返回两个FileInfo列表之间的差异集?

C# 如何在忽略文件扩展名的情况下返回两个FileInfo列表之间的差异集?,c#,list,generics,ienumerable,set-difference,C#,List,Generics,Ienumerable,Set Difference,我有两个要比较的IEnumerable列表: IEnumerable<FileInfo> list1 = dir1.GetFiles("*" + _ext1, SearchOption.AllDirectories); IEnumerable<FileInfo> list2 = dir2.GetFiles("*" + _ext2, SearchOption.AllDirectories); 因此,list1将类似于: file1.jpg file2.jpg file3.

我有两个要比较的
IEnumerable
列表:

IEnumerable<FileInfo> list1 = dir1.GetFiles("*" + _ext1, SearchOption.AllDirectories);
IEnumerable<FileInfo> list2 = dir2.GetFiles("*" + _ext2, SearchOption.AllDirectories);
因此,
list1
将类似于:

file1.jpg
file2.jpg
file3.jpg
file4.jpg
file5.jpg
file6.jpg
list2
将如下所示:

file1.png
file2.png
file4.png
我想在列表2中找到列表1中不存在的所有内容。我尝试了以下方法:

List<string> list1FileNames = list1.Select(f => Path.GetFileNameWithoutExtension(f.FullName)).ToList();
List<string> list2FileNames = list2.Select(f => Path.GetFileNameWithoutExtension(f.FullName)).ToList();
var setDiff = list1FileNames .Except(list2FileNames );
然而,我真正想要的是得到一个FileInfo的列表,而不仅仅是文件名字符串。我需要这个,因为我需要其他信息,如完整文件路径,ext。。因此,仅仅列出文件名字符串并不能完成此任务。我怎样才能做到这一点呢?

您可以将
Where()
All()
结合使用,但时间复杂度很高:

var difference =  list2
                  .Where(f=>list1.All(x=>Path.GetFileNameWithoutExtension(x.FullName) != Path.GetFileNameWithoutExtension(f.FullName)); 
您可以将
Where()
All()
一起使用,但它的时间复杂度很高:

var difference =  list2
                  .Where(f=>list1.All(x=>Path.GetFileNameWithoutExtension(x.FullName) != Path.GetFileNameWithoutExtension(f.FullName)); 
那么:

IEnumerable<FileInfo> list1 = dir1.GetFiles("*" + _ext1, SearchOption.AllDirectories);
IEnumerable<FileInfo> list2 = dir2.GetFiles("*" + _ext2, SearchOption.AllDirectories);

IEnumerable<FileInfo> filtered = list2.Where(f2 => !list1.Any(f1 =>
    Path.GetFileNameWithoutExtension(f1.FullName) == Path.GetFileNameWithoutExtension(f2.FullName)));
IEnumerable list1=dir1.GetFiles(“*”+\u ext1,SearchOption.AllDirectories);
IEnumerable list2=dir2.GetFiles(“*”+_ext2,SearchOption.AllDirectories);
IEnumerable filtered=list2.Where(f2=>!list1.Any(f1=>
Path.GetFileNameWithoutExtension(f1.FullName)==Path.GetFileNameWithoutExtension(f2.FullName));
那么:

IEnumerable<FileInfo> list1 = dir1.GetFiles("*" + _ext1, SearchOption.AllDirectories);
IEnumerable<FileInfo> list2 = dir2.GetFiles("*" + _ext2, SearchOption.AllDirectories);

IEnumerable<FileInfo> filtered = list2.Where(f2 => !list1.Any(f1 =>
    Path.GetFileNameWithoutExtension(f1.FullName) == Path.GetFileNameWithoutExtension(f2.FullName)));
IEnumerable list1=dir1.GetFiles(“*”+\u ext1,SearchOption.AllDirectories);
IEnumerable list2=dir2.GetFiles(“*”+_ext2,SearchOption.AllDirectories);
IEnumerable filtered=list2.Where(f2=>!list1.Any(f1=>
Path.GetFileNameWithoutExtension(f1.FullName)==Path.GetFileNameWithoutExtension(f2.FullName));

如果您想提高速度,请尝试以下方法:

private IEnumerable<FileInfo> GetUniqueFilesWithoutExtension(IEnumerable<FileInfo> list1, IEnumerable<FileInfo> list2)
{
    var d = new HashSet<string>();
    foreach (var fi in list2)
    {
        d.Add(Path.GetFileNameWithoutExtension(fi.FullName));
    }

    foreach (var fi in list1)
    {
        if (!d.Contains(Path.GetFileNameWithoutExtension(fi.FullName)))
        {
            yield return fi;
        }
    }
}
private IEnumerable GetUniqueFilesWithoutExtension(IEnumerable列表1,IEnumerable列表2)
{
var d=新的HashSet();
foreach(列表2中的变量fi)
{
d、 添加(Path.GetFileNameWithoutExtension(fi.FullName));
}
foreach(列表1中的变量fi)
{
如果(!d.Contains(Path.GetFileNameWithoutExtension(fi.FullName)))
{
收益率fi;
}
}
}

list2
中创建一个文件名(sans扩展名)的哈希集,然后在
list1
中迭代,只返回带有未出现在
list2
哈希集中的文件名(sans扩展名)的项。
yield return
允许您在以流式方式发现结果时使用这些结果,而不必等待生成整个列表(如果这对您很重要)。

如果您希望提高速度,请尝试以下方法:

private IEnumerable<FileInfo> GetUniqueFilesWithoutExtension(IEnumerable<FileInfo> list1, IEnumerable<FileInfo> list2)
{
    var d = new HashSet<string>();
    foreach (var fi in list2)
    {
        d.Add(Path.GetFileNameWithoutExtension(fi.FullName));
    }

    foreach (var fi in list1)
    {
        if (!d.Contains(Path.GetFileNameWithoutExtension(fi.FullName)))
        {
            yield return fi;
        }
    }
}
private IEnumerable GetUniqueFilesWithoutExtension(IEnumerable列表1,IEnumerable列表2)
{
var d=新的HashSet();
foreach(列表2中的变量fi)
{
d、 添加(Path.GetFileNameWithoutExtension(fi.FullName));
}
foreach(列表1中的变量fi)
{
如果(!d.Contains(Path.GetFileNameWithoutExtension(fi.FullName)))
{
收益率fi;
}
}
}

list2
中创建一个文件名(sans扩展名)的哈希集,然后在
list1
中迭代,只返回带有未出现在
list2
哈希集中的文件名(sans扩展名)的项。
yield return
允许您在以流式方式发现结果时使用结果,而不必等待生成整个列表,如果这对你很重要的话。

看看这个:另请看中的
ExceptBy
方法。看看这个:另请看中的
ExceptBy
方法。我的两个列表中的这个方法似乎花费了很长时间,每个列表都包含9000个项目。我正在想办法加快速度。它只适用于5或6项,但不适用于数千项。@约翰:这是因为对于列表2中的每一项,它都可能检查列表1中的每一项。这里有一个O(n*m)算法。最好在列表1中创建一组文件名,并使用
ISet.Contains()
检查文件名。对于我的两个列表,这个方法似乎花费了很长时间,每个列表都包含大约9000个项目。我正在想办法加快速度。它只适用于5或6项,但不适用于数千项。@约翰:这是因为对于列表2中的每一项,它都可能检查列表1中的每一项。这里有一个O(n*m)算法。最好在列表1中创建一组文件名,并使用
ISet.Contains()
进行检查。您可以使用
new HashSet(列表2.Select(fi=>Path.GetFileNameWithoutExtension(fi.FullName))
来初始化该集。我知道,但我想在没有LINQ的情况下进行此操作。因此,如果我理解正确,一旦找到匹配项,yeild Essentially就会中断第二个循环?事实上,我想我看到了它的作用。它不会中断循环,它会返回一个值,这样您在循环中的位置就不会丢失,也不必重新开始。所以要这么快!很不错的!谢谢是的,
yield return
将数据一次一个地流出来,而不是等到构建完整列表后再返回。返回对象接口只是
IEnumerable
,因此您可以自由定义如何实现枚举。但这可能是我的镀金;只有当您需要在处理结果时使用它们时,这才重要。这不是真正的速度提升的来源。你可以使用
new HashSet(list2.Select(fi=>Path.GetFileNameWithoutExtension(fi.FullName))
来初始化该集。我知道,但我想在没有LINQ的情况下进行初始化。因此,如果我理解正确,一旦找到匹配项,yeild就会自动中断第二个循环。实际上,我想我明白它的作用了。它不会中断循环,它会返回一个值,这样您在循环中的位置就不会丢失,也不必重新开始。所以要这么快!很不错的!谢谢是的,
yield return
将数据一次一个地流出来,而不是等到构建完整列表后再返回。返回对象接口只是
IEnumerable
,因此您可以自由定义如何返回