Where not in OR Except SQL modeling in LINQ for objects

Suppose I have two lists that contain a list of source file names and destination file names, respectively.

Sourcefilenamelist has files like 1.txt, 2.txt, 3.txt, 4.txt

while Destinaitonlist has 1.txt, 2.txt.

I need to write a linq query to find out which files are in the SourceList that are not in the DestinationFile list.

eg. here out put will be 3.txt and 4.txt. I did this with instructions foreach. but now I want to do the same using LINQ (C #).

Edit:

My code

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

And Filelist- this is a simple class containing only one fileNames property of a type string.

class FileList
    {
       public string FileNames { get; set; }
    }
+3
source share
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(); }
}

, Except, Comparer

IEnumerable<FileList> except = sourceFileNames.Except(destinationFileNames, new FileList.FileListComparer() );
+5

, Except :

var files = sourceFilenameList.Except(destinationList);

, , , , : new[] {a, a, b, b, c}.Except(new[] {b, c}) - {a}, {a, a}.

LINQ, IEnumerable<T> - , List, ToList:

var files = sourceFilenameList.Except(destinationList).ToList();

EDIT: , , FileList, , . Equals GetHashCode (, , 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;
    }
}

:

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);
+14
Sourcefilenamelist.Except(Destinaitonlist)
+8

masenkablast, , ( ), .

, struct. class FileList struct FileList, , 3 4

[EDIT] If you want to continue using the class without implementing IEqualityComparer, just implement IEquatable in your class, the idea comes from http://msdn.microsoft.com/en-us/library/bb300779.aspx

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ExceptList
{
    class Program
    {
        static void Main(string[] args)
        {
            var 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" });

            var except = sourceFileNames.Except(destinationFileNames);


            // list only 3 and 4
            foreach (var f in except)
                Console.WriteLine(f.FileNames);

            Console.ReadLine();
        }
    }

    class FileList :  IEquatable<FileList>
    {
        public string FileNames { get; set; }


        #region IEquatable<FileList> Members

        public bool Equals(FileList other)
        {
            //Check whether the compared object is null.
            if (Object.ReferenceEquals(other, null)) return false;

            //Check whether the compared object references the same data.
            if (Object.ReferenceEquals(this, other)) return true;

            return FileNames.Equals(other.FileNames);

        }        

        #endregion

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

}
+2
source

I think Jon Skeet's answer is the best answer, but your other option looks directly at the property you want to compare (file names)

var destNames = destinationFileNames.Select(destName => destName.FileNames);
IEnumerable<FileList> except =  sourceFileNames
    .Where(sourceName => !destNames.Contains(sourceName.FileNames));

or (the same in one expression)

IEnumerable<FileList> except =  sourceFileNames
    .Where(sourceName => !destinationFileNames
        .Select(destNames => destNames.FileNames)
        .Contains(sourceName.FileNames));

edit: thanks for downvote; I checked the code and found an error. He is working now!

0
source

Source: https://habr.com/ru/post/1741246/


All Articles