【问题标题】:LINQ check list of objects contain a value AND not some other values对象的 LINQ 检查列表包含一个值而不是其他一些值
【发布时间】: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" &amp;&amp; t.trackingCode != "CCI" - 第二个谓词是多余的。如果 TrackingCode 等于“DSP”,则它自动不等于“CCI”。您犯了一个典型的错误,即(作为人类)查看跨行的值,但编写的代码比较同一行中的值

标签: c# .net linq


【解决方案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"};
    

    如果您想忽略大小写,那么将dspDSP 视为您需要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,您还可以将一个与&amp;&amp; 一起使用。我更喜欢两个,因为它更容易阅读。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-06
      • 2017-08-21
      • 1970-01-01
      • 1970-01-01
      • 2020-10-04
      • 2019-07-04
      • 2022-01-27
      • 1970-01-01
      相关资源
      最近更新 更多