Reputation: 4079
I have a collection that starts out as XML returned from an API like this:
<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>
The XML is deserialised to typical POCOs:
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; }
}
The API makes no promises regarding the order in which rows are returned, and I want to retrieve the row with the most recent date value. If the date was an actual property on a Row
object then I could use the technique shown in https://stackoverflow.com/a/27686805/319980, (using the Min
LINQ operator to sort the Table.Rows
collection by the Date
property) but that doesn't appear to be an option here, since date is a value on a child collection.
Assuming that the date
field will always be present, can this be done in pure LINQ?
Upvotes: 2
Views: 613
Reputation: 249466
You can use OrderByDescending
and First
operators to obtain the result. Assuming the date
field is always present and that it is a valid date you could write it like this:
table.Rows
.OrderByDescending(r => DateTime.ParseExact(r.Fields.First(f => f.Id == "date").Value, "yyyy-MM-dd", CultureInfo.InvariantCulture))
.First();
If you can add the morelinq
package, you can use the MaxBy
operator:
table.Rows
.MaxBy(r => DateTime.ParseExact(r.Fields.First(f => f.Id == "date").Value, "yyyy-MM-dd", CultureInfo.InvariantCulture));
Upvotes: 2
Reputation: 37299
What you can do is order the Rows
by the date
and then take the first row. To order by the date
you should parse the string:
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();
A more robust version can be to use TryParse
for the date instead of just parsing, and in the case of failure returning DateTime.MinValue
so row is not chosen
Upvotes: 4