一個迭代小算法,根據指定的個數對下標進行分組

不多寫博客,通常都在博客園打醬油,但願你們指點指點。app

實現效果:性能

好比:第一行2個,第二行3個,第三行5個,第四行1個, (2,3,4,1)會一直循環分組,直到所有數據分組完成。ui

代碼以下:spa

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()等,或則會形成最終獲取的數據個別項丟失。3d

性能差很少1一千萬條 130ms對象

 

寫的很差  體諒體諒 (●'◡'●)blog

相關文章
相關標籤/搜索