[c#] compare two list and return not matching items using linq

i have a two list

List<Sent> SentList;
List<Messages> MsgList;

both have the same property called MsgID;

MsgList            SentList  

MsgID Content      MsgID Content Stauts
1       aaa        1       aaa     0
2       bbb        3       ccc     0
3       ccc        
4       ddd
5       eee

i want to compare the MsgID in Msglist with the sentlist and need items which are not in the sent list using linq

Result 

MsgID Content
2       bbb
4       ddd
5       eee

This question is related to c# linq list c#-4.0

The answer is


Well, you already have good answers, but they're most Lambda. A more LINQ approach would be like

var NotSentMessages =
                from msg in MsgList
                where !SentList.Any(x => x.MsgID == msg.MsgID)
                select msg;

List<Car> cars = new List<Car>() {  new Car() { Name = "Ford", Year = 1892, Website = "www.ford.us" }, 
                                    new Car() { Name = "Jaguar", Year = 1892, Website = "www.jaguar.co.uk" }, 
                                    new Car() { Name = "Honda", Year = 1892, Website = "www.honda.jp"} };

List<Factory> factories = new List<Factory>() {     new Factory() { Name = "Ferrari", Website = "www.ferrari.it" }, 
                                                    new Factory() { Name = "Jaguar", Website = "www.jaguar.co.uk" }, 
                                                    new Factory() { Name = "BMW", Website = "www.bmw.de"} };

foreach (Car car in cars.Where(c => !factories.Any(f => f.Name == c.Name))) {
    lblDebug.Text += car.Name;
}

Try,

  public class Sent
{
    public int MsgID;
    public string Content;
    public int Status;

}

public class Messages
{
    public int MsgID;
    public string Content;
}

  List<Sent> SentList = new List<Sent>() { new Sent() { MsgID = 1, Content = "aaa", Status = 0 }, new Sent() { MsgID = 3, Content = "ccc", Status = 0 } };
            List<Messages> MsgList = new List<Messages>() { new Messages() { MsgID = 1, Content = "aaa" }, new Messages() { MsgID = 2, Content = "bbb" }, new Messages() { MsgID = 3, Content = "ccc" }, new Messages() { MsgID = 4, Content = "ddd" }, new Messages() { MsgID = 5, Content = "eee" }};

            int [] sentMsgIDs = SentList.Select(v => v.MsgID).ToArray();
            List<Messages> result1 = MsgList.Where(o => !sentMsgIDs.Contains(o.MsgID)).ToList<Messages>();

Hope it should help.


You can do something like

var notSent = MsgSent.Except(MsgList, MsgIdEqualityComparer);

You will need to provide a custom equality comparer as outlined on MSDN

http://msdn.microsoft.com/en-us/library/bb336390.aspx

Simply have that equality comparer base equality only on MsgID property of each respective type. Since the equality comparer compares two instances of the same type, you would need to define an interface or common base type that both Sent and Messages implement that has a MsgID property.


If u wanna Select items of List from 2nd list:

MainList.Where(p => 2ndlist.Contains(p.columns from MainList )).ToList();


You can do like this,this is the quickest process

Var result = MsgList.Except(MsgList.Where(o => SentList.Select(s => s.MsgID).ToList().Contains(o.MsgID))).ToList();

This will give you expected output.


List<Person> persons1 = new List<Person>
           {
                    new Person {Id = 1, Name = "Person 1"},
                    new Person {Id = 2, Name = "Person 2"},
                    new Person {Id = 3, Name = "Person 3"},
                    new Person {Id = 4, Name = "Person 4"}
           };


        List<Person> persons2 = new List<Person>
           {
                    new Person {Id = 1, Name = "Person 1"},
                    new Person {Id = 2, Name = "Person 2"},
                    new Person {Id = 3, Name = "Person 3"},
                    new Person {Id = 4, Name = "Person 4"},
                    new Person {Id = 5, Name = "Person 5"},
                    new Person {Id = 6, Name = "Person 6"},
                    new Person {Id = 7, Name = "Person 7"}
           };
        var output = (from ps1 in persons1
                      from ps2 in persons2
                      where ps1.Id == ps2.Id
                      select ps2.Name).ToList();

Person class

public class Person
{        
    public int Id { get; set; }       

    public string Name { get; set; }
}

The naive approach:

MsgList.Where(x => !SentList.Any(y => y.MsgID == x.MsgID))

Be aware this will take up to m*n operations as it compares every MsgID in SentList to each in MsgList ("up to" because it will short-circuit when it does happen to match).


You could do something like:

HashSet<int> sentIDs = new HashSet<int>(SentList.Select(s => s.MsgID));

var results = MsgList.Where(m => !sentIDs.Contains(m.MsgID));

This will return all messages in MsgList which don't have a matching ID in SentList.


As an extension method

public static IEnumerable<TSource> AreNotEqual<TSource, TKey, TTarget>(this IEnumerable<TSource> source, Func<TSource, TKey> sourceKeySelector, IEnumerable<TTarget> target, Func<TTarget, TKey> targetKeySelector) 
{
    var targetValues = new HashSet<TKey>(target.Select(targetKeySelector));

    return source.Where(sourceValue => targetValues.Contains(sourceKeySelector(sourceValue)) == false);
}

eg.

public class Customer
{
    public int CustomerId { get; set; }
}

public class OtherCustomer
{
    public int Id { get; set; }
}


var customers = new List<Customer>()
{
    new Customer() { CustomerId = 1 },
    new Customer() { CustomerId = 2 }
};

var others = new List<OtherCustomer>()
{
    new OtherCustomer() { Id = 2 },
    new OtherCustomer() { Id = 3 }
};

var result = customers.AreNotEqual(customer => customer.CustomerId, others, other => other.Id).ToList();

Debug.Assert(result.Count == 1);
Debug.Assert(result[0].CustomerId == 1);

Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to linq

Async await in linq select How to resolve Value cannot be null. Parameter name: source in linq? What does Include() do in LINQ? Selecting multiple columns with linq query and lambda expression System.Collections.Generic.List does not contain a definition for 'Select' lambda expression join multiple tables with select and where clause LINQ select one field from list of DTO objects to array The model backing the 'ApplicationDbContext' context has changed since the database was created Check if two lists are equal Why is this error, 'Sequence contains no elements', happening?

Examples related to list

Convert List to Pandas Dataframe Column Python find elements in one list that are not in the other Sorting a list with stream.sorted() in Java Python Loop: List Index Out of Range How to combine two lists in R How do I multiply each element in a list by a number? Save a list to a .txt file The most efficient way to remove first N elements in a list? TypeError: list indices must be integers or slices, not str Parse JSON String into List<string>

Examples related to c#-4.0

Xml Parsing in C# EPPlus - Read Excel Table How to add and get Header values in WebApi How to make all controls resize accordingly proportionally when window is maximized? How to use jquery or ajax to update razor partial view in c#/asp.net for a MVC project How to get first record in each group using Linq How to get first object out from List<Object> using Linq ASP.Net MVC - Read File from HttpPostedFileBase without save .NET NewtonSoft JSON deserialize map to a different property name Datetime in C# add days