我有2个清单。第一个是包含一堆对象的主列表,每个对象都有时间戳(Datetime),type(int),value(double)和flag(int)。第二个列表有type(int)和description(string)。
我的问题是我需要第一个列表在每个时间戳都有所有类型。在没有这种对象匹配(timestamp,type)的情况下,我需要插入一个带有(timestamp,type,null value和null flags)的新对象。
如何使用Linq做到这一点?
示例对象:
var date = DateTime.UtcNow;
var points = new List<Point> {
new Point { ts_utc = date , type = 300, value = 25 , flags = 0 },
new Point { ts_utc = date , type = 400, value = 250 , flags = 0 },
new Point { ts_utc = date , type = 500, value = 2500 , flags = 0 },
new Point { ts_utc = date.AddDays(1) , type = 300, value = 26 , flags = 0 },
//new Point { ts_utc = date.AddDays(1) , type = 400, value = 260, flags = 0 },
new Point { ts_utc = date.AddDays(1) , type = 500, value = 2600 , flags = 0 },
new Point { ts_utc = date.AddDays(2) , type = 300, value = 27 , flags = 0 },
new Point { ts_utc = date.AddDays(2) , type = 400, value = 270 , flags = 0 },
new Point { ts_utc = date.AddDays(2) , type = 500, value = 2700 , flags = 0 }
};
var desc = new List<Description> {
new Description{ type = 300, description = "300" },
new Description{ type = 400, description = "400" },
new Description{ type = 500, description = "500" },
};
var q = from p in points
join d in desc on p.type equals d.type into joined
from subd in joined.DefaultIfEmpty(...)
...
查询不完整。在上面的列表中,我评论了一个Point作为该(时间戳,类型)组合的缺失值的示例。在该位置,我希望使用现有类型的时间戳插入默认对象,但插入缺少的类型。值和标志应为null。我猜一个小组可能派上用场了吗?
答案 0 :(得分:1)
如果我理解正确,您需要第一个集合中不存在的时间戳和类型组合,这些集合基于具有时间戳的一个条目的集合,而不是第二个集合中的所有类型。
var missing = points.GroupBy(p => p.ts_utc)
.SelectMany(g => desc.Where(d => g.All(p => p.type != d.type))
.Select(d => new
{
ts = g.Key,
type = d.type
}));
这将首先按时间戳对点进行分组,然后对于每个分组,它将从描述列表中过滤出组中存在类型的任何描述,只留下具有此类型不存在的类型的描述时间戳。然后它从组密钥和“缺失”类型中选择时间戳。最后SelectMany
会使结果变平。
然后,您可以迭代结果并将条目添加到points
集合中。
foreach(var m in missing)
points.Add(new Point { ts_utc = m.ts, type = m.type });
答案 1 :(得分:1)
如果我错了,但是你想为列表1“填补空白”,请纠正我 - 这样它包含每个现有日期的每个现有类型的条目?
如果是这样,我会让所有不同的项目迭代并创建一个嵌套的foreach循环......
List<DateTime> allExistingDates = points.Select(o => o.ts_utc).Distinct().ToList();
List<int> allExistingTypes = points.Select(o => o.type).Concat(desc.Select(o => o.type)).Distinct().ToList();
foreach (DateTime d in allExistingDates)
foreach (int t in allExistingTypes)
if (points.Any(o => o.ts_utc == d && o.type == t) == false)
points.Add(new Point { ts_utc = d, type = t});
答案 2 :(得分:0)
我发现这可以修复我的列表,而不必诉诸多个查询:
SELECT DISTINCT Thread.Id, Thread_Account.Account, etc..
我认为它不会比这更短。两个(此时)其他答案都帮助我达成了这个解决方案。它没有创建不必要的新点,是1 linq查询,我认为(使用1 linq查询)它不会更有效率。