通过子分集

时间:2017-12-05 05:05:40

标签: c# linq

我有一个集合,最初是从这样的API返回的XML:

<table>
   <row id="1">
      <field id="date">2017-01-02</field>
      <field id="salary">125000</field>
   </row>
   <row id="2">
      <field id="date">2016-01-02</field>
      <field id="salary">130000</field>
   </row>
</table>

将XML反序列化为典型的POCO:

public class Table
{
   public Row[] Rows { get;set; }
}

public class Row
{
   public Field[] Fields { get;set; }
}

public class Field
{
    public string Id { get;set; }
    public string Value { get;set; }
}

API没有对返回行的顺序做出任何承诺,我想要检索具有最新日期值的行。如果日期是Row对象上的实际属性,那么我可以使用https://stackoverflow.com/a/27686805/319980中显示的技术,(使用Min LINQ运算符对Table.Rows集合进行排序。 Date属性)但这似乎不是一个选项,因为日期是子集合的值。

假设date字段始终存在,可以在纯LINQ中完成吗?

2 个答案:

答案 0 :(得分:4)

您可以做的是按Rows订购date,然后选择第一行。要按date排序,您应该解析字符串:

var result = table.Rows.OrderByDescending(r => DateTime.ParseExact(
    r.Fields.FirstOrDefault(f => f.Id == "date")?.Value ?? DateTime.MinValue.ToString("yyyy-MM-dd"),
    "yyyy-MM-dd", 
    CultureInfo.InvariantCulture)).FirstOrDefault();

更强大的版本可以使用TryParse作为日期而不仅仅是解析,并且在失败的情况下返回DateTime.MinValue因此不选择行

答案 1 :(得分:2)

您可以使用OrderByDescendingFirst运算符来获取结果。假设date字段始终存在并且它是有效日期,您可以这样写:

table.Rows
    .OrderByDescending(r => DateTime.ParseExact(r.Fields.First(f => f.Id == "date").Value, "yyyy-MM-dd", CultureInfo.InvariantCulture))
    .First();

如果您可以添加morelinq包,则可以使用MaxBy运算符:

table.Rows
    .MaxBy(r => DateTime.ParseExact(r.Fields.First(f => f.Id == "date").Value, "yyyy-MM-dd", CultureInfo.InvariantCulture));