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
compare two list and return not matching items using linq
提问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,因为它比较每一个操作MsgID中SentList,以各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 属性进行相等。由于相等比较器比较相同类型的两个实例,因此您需要定义Sent和Messages实现的具有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; }
}

