C# 使用linq比较两个列表并返回不匹配的项目

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11957685/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 19:50:19  来源:igfitidea点击:

compare two list and return not matching items using linq

c#linqlistc#-4.0

提问by Spen D

i have a two list

我有两个清单

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

both have the same property called MsgID;

两者都具有相同的属性,称为 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

我想将 Msglist 中的 MsgID 与发送列表进行比较,并且需要使用 linq 发送列表中没有的项目

Result 

MsgID Content
2       bbb
4       ddd
5       eee

回答by lc.

The naive approach:

天真的方法:

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

Be aware this will take up to m*noperations as it compares every MsgIDin SentListto each in MsgList("up to" because it will short-circuit when it doeshappen to match).

请注意,这将需要最多m*n,因为它比较每一个操作MsgIDSentList,以各MsgList(“达人”,因为它会短路,当它没有正好匹配)。

回答by Reed Copsey

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 MsgListwhich don't have a matching ID in SentList.

这将返回在MsgList中没有匹配 ID 的所有消息SentList

回答by Eric J.

You can do something like

你可以做类似的事情

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

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

您将需要提供 MSDN 上概述的自定义相等比较器

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

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 Sentand Messagesimplement that has a MsgIDproperty.

简单地让相等比较器仅基于每个相应类型的 MsgID 属性进行相等。由于相等比较器比较相同类型的两个实例,因此您需要定义SentMessages实现的具有MsgID属性的接口或公共基类型。

回答by Tys

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

回答by Andre Calil

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

好吧,您已经有了很好的答案,但它们大多是 Lambda。更多的 LINQ 方法就像

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

回答by Jignesh Thakker

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.

希望它应该有所帮助。

回答by Tushar patel

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.

这将为您提供预期的输出。

回答by Matt Searles

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

回答by Sapnandu

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