说明:可以将一组数字分到组 Arr[n] n [seed,limit] 里。
比如 有一大筐水果 有大有小有苹果,有菠萝,榴莲,要求1大小相似的尽量放到一个框里,要求2同类型的水果尽量放一个框
一个框可以盛 20 - 40 个水果
这样分出来可以是
case 1 : 20 35 40 20 19
case 2: 20 35 40 20 1
这样就需要吧最后一个平摊到其他框,目前是放到前一个框里,分摊算法要看排序的重要程度和实际情况了。
/// <summary> /// 动态分组算法 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="source">源</param> /// <param name="seed">种子</param> /// <param name="limit">每组最大限制数量</param> /// <param name="breakFunc">分组函数</param> /// <param name="flatLimit">扁平数量限制</param> /// <returns></returns> public static List<List<T>> Group<T>(this List<T> source, int seed, int limit, Func<List<T>, T, bool> breakFunc, FlatGroupType flatType = FlatGroupType.None, int? flatLimit = null) { var res = new List<List<T>>(); while (true) { var buffer = source.Take(20).ToList(); if (buffer.Count == 0) break; var last = buffer.Last(); var inter = source.Except(buffer).ToList().GetEnumerator(); while (true) { inter.MoveNext(); var current = inter.Current; if (current == null || breakFunc(buffer, current) || buffer.Count == 40) { break; } buffer.Add(current); } res.Add(buffer); source = source.Except(buffer).ToList(); buffer = new List<T>(); } if (res.Last().Count < seed) { if (flatLimit == null) { flatLimit = seed; } new FlatGroup(flatType).FlatLast(res, flatLimit.Value); } return res; } public class FlatGroup { private readonly FlatGroupType flatType; public FlatGroup(FlatGroupType flatGroupType) { flatType = flatGroupType; } internal void FlatLast<T>(List<List<T>> source, int flatLimit) { if (source.Count == 1) return; var last = source.Last(); if (last.Count <= flatLimit) { source.Remove(last); Flat(source, last); } } internal void Flat<T>(List<List<T>> source, List<T> toFlat) { if (flatType == FlatGroupType.PushUp) { source.Last().AddRange(toFlat); } } }