一个迭代小算法,根据指定的个数对下标进行分组
2014-03-27 22:45 兜兜里没有药 阅读(286) 评论(0) 编辑 收藏 举报很少写博客,一般都在博客园打酱油,希望大家指点指点。
实现效果:
比如:第一行2个,第二行3个,第三行5个,第四行1个, (2,3,4,1)会一直循环分组,直到全部数据分组完成。
代码如下:
using System; using System.Collections.Generic; using System.Linq; namespace Bulrush.Linq.Wrappers { /// <summary> /// 分组包装器 /// </summary> /// <typeparam name="T">要分组的对象的类型</typeparam> public sealed class GroupByWrapper<T> { readonly IEnumerable<T> _dataSource; /// <summary> /// 构造分组包装器 /// </summary> /// <param name="dataSource">要进行分组的数据源</param> public GroupByWrapper(IEnumerable<T> dataSource) { _dataSource = dataSource; } /// <summary> /// 根据指定每组的个数进行分组 /// <remarks> /// 将循环每组的个数集合进行分组,直到全部数据分组完成 /// </remarks> /// </summary> /// <param name="counts">每组的个数集合</param> public IEnumerable<IGrouping<int, T>> Get(IEnumerable<int> counts) { if (counts == null || counts.Count() < 1) throw new ArgumentNullException("counts"); var countEnumerator = counts.GetEnumerator(); var dataEnumerator = _dataSource.GetEnumerator(); int curIndex = 0; Grouping<int, T> group; do { if (!dataEnumerator.MoveNext()) break; group = BuildGroup(curIndex, dataEnumerator, countEnumerator); yield return group; curIndex++; } while (true); } #region 私有方法成员 private Grouping<int, T> BuildGroup(int index, IEnumerator<T> data, IEnumerator<int> counts) { var group = new Grouping<int, T>(); if (!counts.MoveNext()) { counts.Reset(); counts.MoveNext(); } group.Key = index; group.Source = BuildGroupSource(data, counts.Current).ToList(); return group; } private IEnumerable<T> BuildGroupSource(IEnumerator<T> data, int count) { while (count > 0) { yield return data.Current; count--; if (count <= 0) //如果当前组已完成,退出 break; if (!data.MoveNext()) //如果所有数据分组完成,退出 break; } } #endregion } internal class Grouping<TKey, TElement> : IGrouping<TKey, TElement> { public TKey Key { get; set; } protected internal IEnumerable<TElement> Source { get; set; } public IEnumerator<TElement> GetEnumerator() { return Source.GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } }
使用迭代yield return的时候需要注意不要中途去获取数据,入.Count(), ToList()等,或则会造成最终获取的数据个别项丢失。
性能差不多1一千万条 130ms
写的不好 体谅体谅 (●'◡'●)