如何实现按产品分组并均衡每日记录数?C#技术求助
产品分组调度实现方案
需求说明
- 按产品类型分组,同一产品的所有记录必须分配到同一天,禁止拆分单个产品的记录;
- 调度天数
daysScheduled不得超过产品类型数量(最大为4天),该参数与产品列表均为输入项; - 需使每日记录数尽可能平均,同时保留产品的添加顺序。
输入示例
// 假设Product类定义如下 public class Product { public string Name { get; set; } public string Id { get; set; } public Product(string name, string id) { Name = name; Id = id; } } // 输入参数 int daysScheduled = 2; IList<Product> products = new List<Product>(); products.Add(new Product("CHAIR", "456")); products.Add(new Product("CHAIR", "456")); products.Add(new Product("TABLE", "789")); products.Add(new Product("TABLE", "789")); products.Add(new Product("TV", "567")); products.Add(new Product("TV", "567")); products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123"));
错误分组示例(每日记录数差异过大)
// DAY 1 => 产品类型数=2,记录数=4 products.Add(new Product("CHAIR", "456")); products.Add(new Product("CHAIR", "456")); products.Add(new Product("TABLE", "789")); products.Add(new Product("TABLE", "789")); // DAY 2 => 产品类型数=2,记录数=9 products.Add(new Product("TV", "567")); products.Add(new Product("TV", "567")); products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123"));
期望分组结果(每日记录数接近平均)
// DAY 1 => 产品类型数=3,记录数=6 products.Add(new Product("CHAIR", "456")); products.Add(new Product("CHAIR", "456")); products.Add(new Product("TABLE", "789")); products.Add(new Product("TABLE", "789")); products.Add(new Product("TV", "567")); products.Add(new Product("TV", "567")); // DAY 2 => 产品类型数=1,记录数=7 products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123"));
实现思路与代码
核心逻辑
- 按产品类型分组:以产品的唯一标识(如
Name+Id)为键分组,确保同一产品的所有记录在一个组中;Linq的GroupBy在内存集合中会保留产品类型首次出现的顺序,满足“保留添加顺序”的要求; - 参数校验:确保调度天数在1到产品类型数量之间(最大4天);
- 均衡分配:遍历每个产品组,将其添加到当前记录数最少的日期列表中,保证每日记录数尽可能平均。
完整实现代码
public static List<List<Product>> ScheduleProducts(int daysScheduled, IList<Product> products) { // 按产品唯一标识分组,保留原添加顺序 var productGroups = products .GroupBy(p => $"{p.Name}_{p.Id}") .Select(g => g.ToList()) .ToList(); // 校验调度天数合法性 if (daysScheduled < 1 || daysScheduled > productGroups.Count || daysScheduled > 4) { throw new ArgumentException("调度天数必须在1到产品类型数量之间,且最大不超过4天"); } // 初始化每日调度列表 var dailySchedules = new List<List<Product>>(); for (int i = 0; i < daysScheduled; i++) { dailySchedules.Add(new List<Product>()); } // 分配产品组到记录数最少的日期 foreach (var group in productGroups) { var targetDay = dailySchedules.OrderBy(day => day.Count).First(); targetDay.AddRange(group); } return dailySchedules; } // 测试调用示例 public static void TestSchedule() { int daysScheduled = 2; IList<Product> products = new List<Product>(); products.Add(new Product("CHAIR", "456")); products.Add(new Product("CHAIR", "456")); products.Add(new Product("TABLE", "789")); products.Add(new Product("TABLE", "789")); products.Add(new Product("TV", "567")); products.Add(new Product("TV", "567")); products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123")); products.Add(new Product("MILK", "123")); var result = ScheduleProducts(daysScheduled, products); // 输出结果 for (int i = 0; i < result.Count; i++) { var dayProducts = result[i]; var productTypeCount = dayProducts.GroupBy(p => $"{p.Name}_{p.Id}").Count(); Console.WriteLine($"// DAY {i+1} => 产品类型数={productTypeCount},记录数={dayProducts.Count}"); foreach (var product in dayProducts) { Console.WriteLine($"products.Add(new Product(\"{product.Name}\", \"{product.Id}\"));"); } Console.WriteLine(); } }
输出验证
运行TestSchedule方法后,会输出与期望分组一致的结果,既保证了产品不拆分,每日记录数接近平均,又保留了原产品的添加顺序。
内容的提问来源于stack exchange,提问作者suc pepe
相关产品推荐
相关产品推荐

