42

我有两个清单

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

两者都具有称为 MsgID 的相同属性;

MsgList            SentList  

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

我想将 Msglist 中的 MsgID 与 sentlist 进行比较,并需要使用 linq 不在已发送列表中的项目

Result 

MsgID Content
2       bbb
4       ddd
5       eee
4

10 回答 10

52

您可以执行以下操作:

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

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

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

于 2012-08-14T17:36:17.473 回答
29

天真的方法:

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

请注意,这将占用m*n操作,因为它将每个MsgIDinSentList与每个 in进行比较(“最多”,因为它在匹配时MsgList短路)。

于 2012-08-14T17:36:02.047 回答
17

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

var NotSentMessages =
                from msg in MsgList
                where !SentList.Any(x => x.MsgID == msg.MsgID)
                select msg;
于 2012-08-14T17:52:14.233 回答
10

你可以这样做,这是最快的过程

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

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

于 2016-09-08T11:53:58.043 回答
8

你可以做类似的事情

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

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

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

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

于 2012-08-14T17:36:33.093 回答
2

尝试,

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

希望它应该有所帮助。

于 2012-09-09T12:19:30.690 回答
0

作为扩展方法

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

例如。

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);
于 2017-11-09T07:38:45.373 回答
0
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();

人物类

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

    public string Name { get; set; }
}
于 2019-07-22T12:29:06.633 回答
0

如果您想从第二个列表中选择列表项:

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

于 2020-12-01T07:01:53.667 回答
-1
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;
}
于 2012-08-14T17:44:06.293 回答