对象的 LINQ 检查列表包含一个值而不是其他一些值
Posted
技术标签:
【中文标题】对象的 LINQ 检查列表包含一个值而不是其他一些值【英文标题】:LINQ check list of objects contain a value AND not some other values 【发布时间】:2022-01-04 14:48:32 【问题描述】:假设我有这个对象列表:
var shipments = new List<ShipmentTracking>()
new ShipmentTracking()
trackingNumber = "32021001000", trackings = new List<Tracking>()
new Tracking() trackingCode = "EBC", trackingPoint = "Entered", trackingDateTime = DateTime.Now, trackingMemo = ""
,
new ShipmentTracking()
trackingNumber = "32021001001", trackings = new List<Tracking>()
new Tracking() trackingCode = "EBC", trackingPoint = "Entered", trackingDateTime = DateTime.Now.AddDays(1), trackingMemo = "" ,
new Tracking() trackingCode = "AWB", trackingPoint = "Registered", trackingDateTime = DateTime.Now.AddDays(1), trackingMemo = ""
,
new ShipmentTracking()
trackingNumber = "32021001002", trackings = new List<Tracking>()
new Tracking() trackingCode = "EBC", trackingPoint = "Entered", trackingDateTime = DateTime.Now.AddDays(2), trackingMemo = "" ,
new Tracking() trackingCode = "AWB", trackingPoint = "Registered", trackingDateTime = DateTime.Now.AddDays(2), trackingMemo = "" ,
new Tracking() trackingCode = "DSP", trackingPoint = "Shipped", trackingDateTime = DateTime.Now.AddDays(2), trackingMemo = ""
,
new ShipmentTracking()
trackingNumber = "32021001003", trackings = new List<Tracking>()
new Tracking() trackingCode = "EBC", trackingPoint = "Entered", trackingDateTime = DateTime.Now.AddDays(3), trackingMemo = "" ,
new Tracking() trackingCode = "AWB", trackingPoint = "Registered", trackingDateTime = DateTime.Now.AddDays(3), trackingMemo = "" ,
new Tracking() trackingCode = "DSP", trackingPoint = "Shipped", trackingDateTime = DateTime.Now.AddDays(3), trackingMemo = "" ,
new Tracking() trackingCode = "CCI", trackingPoint = "Cleared", trackingDateTime = DateTime.Now.AddDays(3), trackingMemo = ""
,
new ShipmentTracking()
trackingNumber = "32021001004", trackings = new List<Tracking>()
new Tracking() trackingCode = "EBC", trackingPoint = "Entered", trackingDateTime = DateTime.Now.AddDays(4), trackingMemo = "" ,
new Tracking() trackingCode = "AWB", trackingPoint = "Registered", trackingDateTime = DateTime.Now.AddDays(4), trackingMemo = "" ,
new Tracking() trackingCode = "DSP", trackingPoint = "Shipped", trackingDateTime = DateTime.Now.AddDays(4), trackingMemo = "" ,
new Tracking() trackingCode = "CCI", trackingPoint = "Cleared", trackingDateTime = DateTime.Now.AddDays(4), trackingMemo = "" ,
new Tracking() trackingCode = "POD", trackingPoint = "Delivered", trackingDateTime = DateTime.Now.AddDays(4), trackingMemo = ""
;
我需要只检查并返回具有 trackingCode == "DSP" 但不使用 "CCI" 或 "POD" trackingCode 的货件跟踪的查询,因此在此示例中使用跟踪号 32021001002 进行货件跟踪就是那个。
我试过了,但似乎没有用:
foreach (var shipment in shipments)
var foo = shipment.trackings.FirstOrDefault((t => t.trackingCode == "DSP" && t.trackingCode != "CCI"));
if (shipment.trackings.Contains(foo))
感谢任何帮助或指针。 谢谢!
【问题讨论】:
t.trackingCode == "DSP" && t.trackingCode != "CCI"
- 第二个谓词是多余的。如果 TrackingCode 等于“DSP”,则它自动不等于“CCI”。您犯了一个典型的错误,即(作为人类)查看跨行的值,但编写的代码比较同一行中的值
【参考方案1】:
您希望在跟踪列表中发货:有任何跟踪代码“DSP”并且没有任何跟踪代码“CCI”
shipments.Where(s =>
s.Trackings.Any(t => t.TrackingCode == "DSP") &&
!s.Trackings.Any(t => t.TrackingCode == "CCI")
);
你也可以这样写:
shipments.Where(s =>
s.Trackings.Any(t => t.TrackingCode == "DSP") &&
s.Trackings.All(t => t.TrackingCode != "CCI")
);
即有任何跟踪代码是 DSP 且所有跟踪代码都不是 CCI 的货件"
使用对你更有意义的那个
【讨论】:
【参考方案2】:有 trackingCode == "DSP" 但没有使用 "CCI" 或 “豆荚”
我会填写两个集合以简化它并使其易于更改:
var validCodes = new List<string>"DSP";
var invalidCodes = new List<string>"CCI", "POD";
如果您想忽略大小写,那么将dsp
和DSP
视为您需要StringComparer.OrdinalIgnoreCase
,否则StringComparer.Ordinal
。
查询很简单:
List<ShipmentTracking> trackingList = shipments
.Where(st => st.trackings.Any(t => validCodes.Contains(t.trackingCode, StringComparer.OrdinalIgnoreCase)))
.Where(st => !st.trackings.Any(t => invalidCodes.Contains(t.trackingCode, StringComparer.OrdinalIgnoreCase)))
.ToList();
除了两个Where
,您还可以将一个与&&
一起使用。我更喜欢两个,因为它更容易阅读。
【讨论】:
以上是关于对象的 LINQ 检查列表包含一个值而不是其他一些值的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Linq where 条件检查字符串列表是不是包含任何字符串