score:3

Accepted answer

The key is breaking the two groups down into dictionaries, using the dates from the first list as the keys to the dictionary, and picking the closest key after the second list item date as the key for the second dictionary.

Once you have the two dictionaries, each using a common key value for the types and the subtypes you can just do a GroupJoin and SelectMany to get the results in a sorted list.

(* Note that the answer is based on a slightly different, earlier version of the question, I'm not going to take the time to update the answer because I think the fundamental problem is illustrated and solved in this answer already)

update 2 I realize the problem you're seeing with the First() call is that some of your subalert items might be newer than any other alert item which would cause your exception. I addressed that by adding a 'surrogate' key to the first dictionary using DateTime::MaxValue, and then I no longer filter out the subalerts from the first list, I just use .Distinct() on the final result to remove duplicates

Using linqpad I mocked up this question and solved it using dictionaries and GroupJoin

var all = new []{
    new {date = DateTime.Parse("2012-12-23"), type = "alert", value = 1, accountId = 333 },
    new {date = DateTime.Parse("2012-12-21"), type = "alert", value = 2, accountId = 333 },
    new {date = DateTime.Parse("2012-12-20"), type = "alert", value = 3, accountId = 333 },
    new {date = DateTime.Parse("2012-12-18"), type = "alert", value = 4, accountId = 333 },
    new {date = DateTime.Parse("2012-12-12"), type = "alert", value = 5, accountId = 333 },
    new {date = DateTime.Parse("2012-11-22"), type = "alert", value = 1, accountId = 333 },
    new {date = DateTime.Parse("2012-11-16"), type = "alert", value = 2, accountId = 333 },
    new {date = DateTime.Parse("2012-11-12"), type = "alert", value = 3, accountId = 333 },
    new {date = DateTime.Parse("2012-12-19"), type = "subalert", value = 1, accountId = 333 },
    new {date = DateTime.Parse("2012-12-18"), type = "subalert", value = 2, accountId = 333 },
    new {date = DateTime.Parse("2012-12-04"), type = "subalert", value = 3, accountId = 333 },
    new {date = DateTime.Parse("2012-12-01"), type = "subalert", value = 4, accountId = 333 },
    new {date = DateTime.Parse("2012-11-14"), type = "subalert", value = 1, accountId = 333 },
    new {date = DateTime.Parse("2012-11-08"), type = "subalert", value = 2, accountId = 333 },  
/*add*/ new {date = DateTime.Parse("2012-12-25"), type = "subalert", value = 9, accountId = 333 },  
};

var first = all
    .Where(a=>a.accountId == 333 /* removed && type != "alert" */)
    .OrderByDescending(a=>a.date)
    .GroupBy(a=>a.date.Date)
    .ToDictionary(g=>g.Key);

var firstKeys = first.Keys
    .Cast<DateTime>()
    .Union(new []{DateTime.MaxValue}) /* added this 'surrogate' key */
    .OrderBy(k=>k)
    .ToArray();

var second = all
    .Where(a=>a.accountId == 333 && a.type == "subalert")
    .OrderBy(a=>a.date.Month)
    .GroupBy(a=>a.date.Month)
    .ToDictionary(g=>firstKeys.First(k=>k > g.OrderByDescending(a=>a.date).FirstOrDefault().date));


var combined = first
    .GroupJoin(
        second,
        fk=>fk.Key,
        sk=>sk.Key,
        (d,l)=>d.Value
            .Union(l.SelectMany(i=>i.Value).ToArray()))
    .SelectMany(i=>i)
    .Distinct(); /* Added this to remove duplicates */

combined.Dump();

Which yields:

Updated Results


Related Articles