2012-08-14 138 views
17

回报不匹配的项目,我有一个两个列表比较两个列表,并使用LINQ

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 

我想给的MsgID与sentlist比较Msglist,需要使用LINQ

Result 

MsgID Content 
2  bbb 
4  ddd 
5  eee 
+3

不要忘记标记为*正确*与您的问题=) – 2012-08-16 16:43:19

回答

12

天真的做法,是不是在发送列表中的项目:

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

注意这将需要m*n作业,因为它会将SentList中的每个MsgIDMsgList中的每个MsgID进行比较(“高达”,因为它会在我短路时t 确实碰巧匹配)。

+2

帮助你。如果你要downvote的答案,你至少可以帮我解释为什么最起码的礼貌。 – 2012-08-14 17:57:48

+0

如何:'MsgList.Where(x => SentList.All(y => y.MsgID == x.MsgID))' – zumalifeguard 2017-05-16 02:45:52

+0

@zumalifeguard我假设你的意思是'!=',如果是的话,那么这是一个逻辑上等价的表达式这应该花费相同的时间。 – 2017-05-17 16:28:40

23

你可以这样做:

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

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

这将在MsgList返回所有的消息不具有匹配的ID在SentList

+1

这可能是最好的办法 – 2012-08-14 17:39:23

8

MSDN上

所概述

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

只要有相等比较基础的平等只能对的MsgID属性,你可以做这样的事情

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

您需要提供自定义相等比较每种类型。由于相等比较比较同类型的两个实例,你需要定义两个发送消息的接口或公共基类型实现具有的MsgID财产。

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

啊,和lc完全一样的解决方案。发布。但是,在这里,您可以通过一个完整且经过测试的示例来获得它。 – Tys 2012-08-14 17:45:15

11

那么,你已经有很好的答案,但他们是最Lambda。更LINQ的办法是像

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

'VAR NotSentMessages = 从MSG在MsgList 其中SentList.Any(X => x.MsgID == msg.MsgID && x.content == msg.content) 选择MSG;!' 这是为更好的对比多个属性(组合键) – 2016-09-27 09:46:06

+0

@AndrewDay是的,但OP说他想检查相等的ID,所以没有必要在这里匹配字符串。 – 2016-09-27 14:05:18

+0

- 所以你的代码是更好的代码,因为它的可扩展性。但那是一个坏评论? – 2016-09-27 14:52:24

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

希望它应该帮助。

3

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

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

这会给你预期的输出。

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