一个迭代小算法,根据指定的个数对下标进行分组
2014-03-27 22:45 兜兜里没有药 阅读(293) 评论(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
写的不好 体谅体谅 (●'◡'●)
浙公网安备 33010602011771号