除非在LINQ to Objects中模拟SQL,否则不在OR中

Thi*_*ing 3 c# linq

假设我有两个列表,分别包含源文件名和目标文件名列表.

Sourcefilenamelist包含1.txt,2.txt,3.txt,4.txt文件

而Destinaitonlist有1.txt,2.txt.

我想写一个linq查询来找出SourceList中哪些文件在DestinationFile列表中不存在.

例如,输出将是3.txt和4.txt.我是通过foreach声明完成的.但现在我想通过使用LINQ(C#)来做同样的事情.

编辑:

我的代码是

List<FileList> sourceFileNames = new List<FileList>();

sourceFileNames.Add(new FileList { FileNames = "1.txt" });
sourceFileNames.Add(new FileList { FileNames = "2.txt" });
sourceFileNames.Add(new FileList { FileNames = "3.txt" });
sourceFileNames.Add(new FileList { FileNames = "4.txt" });

List<FileList> destinationFileNames = new List<FileList>();
destinationFileNames.Add(new FileList { FileNames = "1.txt" });
destinationFileNames.Add(new FileList { FileNames = "2.txt" });

IEnumerable<FileList> except =  sourceFileNames.Except(destinationFileNames);
Run Code Online (Sandbox Code Playgroud)

并且Filelist是一个简单的类,只有一个属性fileNames类型为string.

class FileList
    {
       public string FileNames { get; set; }
    }
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 14

Except是为了:

var files = sourceFilenameList.Except(destinationList);
Run Code Online (Sandbox Code Playgroud)

请注意,这是一个设置操作,因此如果源列表有重复的条目,您将只看到唯一的结果:new[] {a, a, b, b, c}.Except(new[] {b, c})只是{a},不是{a, a}.

像许多LINQ运算符一样,这​​会返回一个IEnumerable<T>- 如果你想要它作为一个List只是调用ToList:

var files = sourceFilenameList.Except(destinationList).ToList();
Run Code Online (Sandbox Code Playgroud)

编辑:好的,现在你已经展示了什么FileList,问题只是你没有实现相等比较.您可以通过覆盖EqualsGetHashCode(可能IEquatable<FileList>)或通过实现来实现此目的IEqualityComparer<T>.但是,你仍然遇到了一个问题:它FileNames是一个可变类型,并且在散列和相等方面通常不能很好地工作.最初两个实例可能相等,然后其中一个可以更改.我建议将其重新实现为不可变类型.像这样的东西:

public sealed class FileList : IEquatable<FileList>
{
    private readonly string fileNames;
    public string FileNames { get { return fileNames; } }

    public FileList(string fileNames)
    {
        // If you want to allow a null FileNames, you'll need to change
        // the code in a few places
        if (fileNames == null)
        {
            throw new ArgumentNullException("fileNames");
        }
        this.fileNames = fileNames;
    }

    public override int GetHashCode()
    {
        return fileNames.GetHashCode();
    }

    public override bool Equals(object other)
    {
        return Equals(other as FileList);
    }

    public bool Equals(FileList other)
    {
        return other != null && other.FileNames == FileNames;
    }
}
Run Code Online (Sandbox Code Playgroud)

您的示例代码可能会变为:

List<FileList> sourceFileNames = new List<FileList>
{
    new FileList("1.txt"),
    new FileList("2.txt"),
    new FileList("3.txt"),
    new FileList("4.txt")
};
List<FileList> destinationFileNames = new List<FileList>
{
    new FileList("1.txt"),
    new FileList("2.txt")
};

IEnumerable<FileList> except =  sourceFileNames.Except(destinationFileNames);
Run Code Online (Sandbox Code Playgroud)


Mar*_*tos 8

Sourcefilenamelist.Except(Destinaitonlist)
Run Code Online (Sandbox Code Playgroud)


sid*_*ews 5

不太难做到.在FileList类中,创建一个继承自IEqualityComparer <>的子类

public class FileListComparer : IEqualityComparer<FileList>
{
    public bool Equals(FileList x, FileList y)
    {
        if (x == null || y == null)
        {
            return false;
        }

        return x.FileNames.Equals(y.FileNames, StringComparison.OrdinalIgnoreCase);
    }

    public int GetHashCode(FileList obj) { return base.GetHashCode(); }
}
Run Code Online (Sandbox Code Playgroud)

然后当您调用Except时,请使用Comparer

IEnumerable<FileList> except = sourceFileNames.Except(destinationFileNames, new FileList.FileListComparer() );
Run Code Online (Sandbox Code Playgroud)

  • 而不是实现单独的IEqualityComparer,使FileList实现`IEquatable <FileList>`更简单.(实际上,在这种特殊情况下,只需覆盖Equals/GetHashCode即可.)另请注意,GetHashCode的实现会忽略它要求使用的文件列表 - 这意味着它将无法匹配相同的文件列表. (2认同)