C# Linq - 将空值和周数添加到列表中
C# Linq - Add Null Values and Week Numbers to a List when they are missing
我已成功使用按类别和周数对列表进行分组没问题。
我面临的问题是如何添加 0 并填写缺少的 WeekNumber 值。
如果我只有 'Cars' 那么它会很好很容易,但我似乎无法正确使用 Distinct() 来遍历每个类别。
当前列表:
预期结果:
如果列表中只有汽车,那么我知道我可以执行以下操作以获得整年的价值。
for (var i = 1; i <= 52; ++i)
{
if (vehicleSales.Count(x => x.x == i) == 0)
{
vehicleSales.Add(new WeeklySalesBreakdown { WeekNumber = i, Value = 0, Category = "Cars" });
}
}
感谢帮助和建议!
我稍微更改了您的代码,现在您可以为原始列表中存在的所有类别添加一整年(52 周)的零值记录:
var categories = vehicleSales.Select(v => v.Category).Distinct().ToList();
foreach(var category in categories)
{
for (var i = 1; i <= 52; ++i)
{
if (!vehicleSales.Any(x => x.Category == category && x.WeekNumber == i))
{
vehicleSales.Add(new WeeklySalesBreakdown { WeekNumber = i, Value = 0, Category = category });
}
}
}
您的示例代码可能会变慢,因为您使用'.Count(x => x.x == i)') 遍历所有条目 52 次(当您有数百万个条目时,这个滚雪球,只有几个条目,您不会注意到太多)。
您可以做的是将数据存储在字典中:
salesBreakdownByCategory = new Dictionary<String, int[]>();
然后您将所有条目都检查一遍:
foreach(var breakdown in vehicleSales)
{
int[] values;
if(!salesBreakdownByCategory.TryGetValue(vehicleSales.Category, out values))
{
values = new int[52]; // every entry in the array is by default 0
salesBreakdownByCategory[vehicleSales.Category] = values;
}
values[vehicleSales.WeekNumber-1] = vehicleSales.Value;
}
这样您就可以将所有数据存储在数组中,但是如果您想要一个列表,则必须再次 运行 遍历您的数据结构:
var result = salesBreakdownByCategory.SelectMany(x=>x.Select( (value,index) => new WeeklySalesBreakdown { WeekNumber = index+1, Value = value, Category = x.Key}));
如果您想避免额外的内存分配并将数据添加到现有列表中,而不是像上面的示例那样将值存储在 int 数组中,您可以改用 bool 数组并设置值对于您找到的每个条目都为真。然后你只需要再次遍历字典并在 bool 未设置为 true
时向原始列表添加一个条目
我已成功使用按类别和周数对列表进行分组没问题。 我面临的问题是如何添加 0 并填写缺少的 WeekNumber 值。 如果我只有 'Cars' 那么它会很好很容易,但我似乎无法正确使用 Distinct() 来遍历每个类别。
当前列表:
预期结果:
如果列表中只有汽车,那么我知道我可以执行以下操作以获得整年的价值。
for (var i = 1; i <= 52; ++i)
{
if (vehicleSales.Count(x => x.x == i) == 0)
{
vehicleSales.Add(new WeeklySalesBreakdown { WeekNumber = i, Value = 0, Category = "Cars" });
}
}
感谢帮助和建议!
我稍微更改了您的代码,现在您可以为原始列表中存在的所有类别添加一整年(52 周)的零值记录:
var categories = vehicleSales.Select(v => v.Category).Distinct().ToList();
foreach(var category in categories)
{
for (var i = 1; i <= 52; ++i)
{
if (!vehicleSales.Any(x => x.Category == category && x.WeekNumber == i))
{
vehicleSales.Add(new WeeklySalesBreakdown { WeekNumber = i, Value = 0, Category = category });
}
}
}
您的示例代码可能会变慢,因为您使用'.Count(x => x.x == i)') 遍历所有条目 52 次(当您有数百万个条目时,这个滚雪球,只有几个条目,您不会注意到太多)。
您可以做的是将数据存储在字典中:
salesBreakdownByCategory = new Dictionary<String, int[]>();
然后您将所有条目都检查一遍:
foreach(var breakdown in vehicleSales)
{
int[] values;
if(!salesBreakdownByCategory.TryGetValue(vehicleSales.Category, out values))
{
values = new int[52]; // every entry in the array is by default 0
salesBreakdownByCategory[vehicleSales.Category] = values;
}
values[vehicleSales.WeekNumber-1] = vehicleSales.Value;
}
这样您就可以将所有数据存储在数组中,但是如果您想要一个列表,则必须再次 运行 遍历您的数据结构:
var result = salesBreakdownByCategory.SelectMany(x=>x.Select( (value,index) => new WeeklySalesBreakdown { WeekNumber = index+1, Value = value, Category = x.Key}));
如果您想避免额外的内存分配并将数据添加到现有列表中,而不是像上面的示例那样将值存储在 int 数组中,您可以改用 bool 数组并设置值对于您找到的每个条目都为真。然后你只需要再次遍历字典并在 bool 未设置为 true
时向原始列表添加一个条目