[英]LINQ check list of objects contain a value AND not some other values
Let's say I have this list of objects:假设我有这个对象列表:
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 = "32021001003", 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 = "" }
}
}
};
I need the query that would check and return only shipment tracking(s) that has trackingCode == "DSP" but not shipment tracking with "CCI" or "POD" trackingCode, so in this example shipment tracking with tracking number 32021001002 would be the one.我需要的查询将检查并仅返回具有 trackingCode == "DSP" 但不使用 "CCI" 或 "POD" trackingCode 的货件跟踪的货件跟踪,因此在此示例中,跟踪号为 32021001002 的货件跟踪将是一。
I have tried this but doesn't seem to work:我已经尝试过了,但似乎不起作用:
foreach (var shipment in shipments)
{
var foo = shipment.trackings.FirstOrDefault((t => t.trackingCode == "DSP" && t.trackingCode != "CCI"));
if (shipment.trackings.Contains(foo))
{
}
}
Any help or pointer is appreciated.任何帮助或指针表示赞赏。 Thanks!
谢谢!
You want shipments where for the list of trackings: there IS any tracking code "DSP" and there IS NOT any tracking code "CCI"您想要在哪里提供跟踪列表:有任何跟踪代码“DSP”并且没有任何跟踪代码“CCI”
shipments.Where(s =>
s.Trackings.Any(t => t.TrackingCode == "DSP") &&
!s.Trackings.Any(t => t.TrackingCode == "CCI")
);
You could also write this as:你也可以这样写:
shipments.Where(s =>
s.Trackings.Any(t => t.TrackingCode == "DSP") &&
s.Trackings.All(t => t.TrackingCode != "CCI")
);
ie shipments where there is any tracking code that is DSP, and all the tracking codes are not CCI"即有任何跟踪代码是 DSP 并且所有跟踪代码都不是 CCI 的货物”
Use whichever makes more sense to you使用对您更有意义的
has trackingCode == "DSP" but not shipment tracking with "CCI" or "POD"
有 trackingCode == "DSP" 但没有带有 "CCI" 或 "POD" 的货物跟踪
I would fill two collections to simplify it and to make it easy to be changed:我将填充两个 collections 以简化它并使其易于更改:
var validCodes = new List<string>{"DSP"};
var invalidCodes = new List<string>{"CCI", "POD"};
If you want to ignore the case, so treat dsp
and DSP
same you need StringComparer.OrdinalIgnoreCase
, otherwise StringComparer.Ordinal
.如果您想忽略这种情况,那么将
dsp
和DSP
视为相同,您需要StringComparer.OrdinalIgnoreCase
,否则StringComparer.Ordinal
。
The query is pretty simple:查询非常简单:
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();
Instead of two Where
you can also use one with &&
.而不是两个
Where
你也可以使用一个&&
。 I prefer two because it's easier to read.我更喜欢两个,因为它更容易阅读。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.