zoukankan      html  css  js  c++  java
  • 一个迭代小算法,根据指定的个数对下标进行分组

    很少写博客,一般都在博客园打酱油,希望大家指点指点。

    实现效果:

    比如:第一行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

    写的不好  体谅体谅 (●'◡'●)

  • 相关阅读:
    centos7 双网口绑定
    centos docker 修改默认存储路径
    Django 操作已经存在的数据库
    package ‘RPMM’ is not available (for R version 3.6.0)
    关于tornado的raise gen.Retuen()
    tornodo学习之路
    关于微信小程序登录机制
    关于微信小程序更新机制
    过渡结束事件
    移动端动效
  • 原文地址:https://www.cnblogs.com/zcylife/p/3629622.html
Copyright © 2011-2022 走看看