I have a collection of items and then group them up by itemID version. For an itemID with the same version value, using the example of four instances with version A
- If three of the “A”s have an empty “Status” while one is populated, take the one with the “Status”
- If all four “A”s have a “Status”, take the one with the latest modified date (do not worry about the value of “Status”)
- If two or three “A”s have a value in “Status” and the others are empty, take the populated one with the latest date modified
- If all four “A”s have an empty “Status”, take the one with the latest modified date
CodePudding user response:
You can use Linq statements. Use Min if you want the earliest date. I didn't know what you mean by the status is "Empty" so the code below is assuming that status is a string and "Empty" in this case means that the string IsNullOrWhiteSpace.
var itemsWithStatus = items.Where(item => string.IsNullOrWhiteSpace(item.Status));
if (itemsWithStatus.Any())
{
return itemsWithStatus.Max(item => item.Date);
}
return items.Max(item => item.Date);
CodePudding user response:
The cases are all notionally the same if you rank "has a status" as eg 1 and "doesn't have a status" as 2 and then order by this preferentially over the date
As such it seems we could have:
items.GroupBy(
i => (i.Id, i.Version),
(k, g) => g.OrderBy(i => i.Status.HasValue ? 1 : 2).ThenByDescending(i => i.DateModified).First()
);
This groups items on a tuple of id and version, then uses the overload of group by that processes it's own groupings after it's made them. The items in the group are sorted first by whether status has a value (and any status of any value takes priority over any non status item) then the modified date is used to split any ties
This form of GroupBy is essentially
items.GroupBy(i => (i.Id, i.Version))
.Select(g =>
g.OrderBy(i => i.Status.HasValue ? 1 : 2)
.ThenByDescending(i => i.DateModified)
.First()
);
which you may prefer
