惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

雷峰网
雷峰网
Y
Y Combinator Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
The Cloudflare Blog
博客园_首页
J
Java Code Geeks
A
About on SuperTechFans
人人都是产品经理
人人都是产品经理
量子位
C
Check Point Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - 三生石上(FineUI控件)
L
LangChain Blog
N
Netflix TechBlog - Medium
Hugging Face - Blog
Hugging Face - Blog
B
Blog
美团技术团队
Microsoft Security Blog
Microsoft Security Blog
P
Proofpoint News Feed
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
宝玉的分享
宝玉的分享
罗磊的独立博客
MongoDB | Blog
MongoDB | Blog
Last Week in AI
Last Week in AI

博客园 - blue1000

[转载]安装网银安全控件 近期学习SQL Server,收藏的几个学习教程网址备忘 DataColumn.Caption属性应用到DataGridView.HeaderText的方法 飞梭TXT文本数据处理百宝箱 - 极速、高效、灵活 中国父母十个错误教育观念[转] asp.net根据域名查ip C#版 - blue1000 - 博客园 asp.net 2.0教程 登录系列控件 asp.net 2.0教程 成员资格和角色管理 asp.net 2.0教程 Web部件WebPart asp.net 2.0教程 个性化用户配置 asp.net 2.0教程 数据缓存 asp.net 2.0教程 数据绑定控件 asp.net 2.0教程 数据源控件2 asp.net 2.0教程 数据源控件 asp.net 2.0教程 其它服务器控件 asp.net 2.0教程 网站导航控件 asp.net 2.0教程 母版页 asp.net 2.0教程 主题和皮肤 asp.net 2.0教程 C# 2.0匿名方法、迭代器、局部类
C#批量生成大数据量无重复随机数据的另类高效实现
blue1000 · 2012-11-30 · via 博客园 - blue1000

注:本文思路已经应用于“飞梭TXT文本数据处理百宝箱”中,有兴趣的朋友可以下载试用。

我们知道,如果需要批量生成海量无重复的随机数据是个很麻烦的事情。如果每次生成都要和之前生成的数据进行比对的话,那效率会随着数据量的增大而越来越低,最后不堪忍受。今天介绍一种另类的思路,可以高效的做到随机数据无重复。

分析:所谓随机数据,就是在某个设定的区间内随机提取一批数据出来。那么我们可以变通的思考一下:我们可不可以将此设定的数据区间A按照所需的数据量N分成N个小的数据区间B,如果这样的话,我们只需要每次从数据区间B中取一个随机值,并且不需要验证是否重复,就可以很容易的得到N个唯一的数据。而这些数据集也是随机的,只不过是稍微带有一定的均布特性。

这里有个问题,按照以上的思路取出的数据虽然是随机的,但是还是按照从小到大的顺序排列,这是个遗憾。解决办法:获取到随机数据集合后,使用洗牌算法对数据进行打乱处理。

实现代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DataGenerator.DataObject
{
    public class RandomData : DynamicDataBase
    {
        private Random m_ro;
        private List<string> m_codes;
        private long m_lastNum;
        private long m_span;
        private char m_padStr;
        public override string GetDataByIndex(int index)
        {
            return m_codes[index];
        }
        public override void Reset(int count)
        {            
            //初始化m_fromNum;根据生成数量设置m_span值
            try
            {
                //m_fromNum = 0;
                
//char[] cs = FromStr.ToArray();
                
//int idx;
                
//for (int i = 0; i < cs.Length; i++)
                
//{
                
//    idx = CharList.IndexOf(cs[i]);
                
//    m_fromNum += Convert.ToInt32(idx * Math.Pow(CharList.Length, cs.Length - i - 1));
                
//}
                
//m_lastNum = m_fromNum - 1;
                m_lastNum = -1L;
                //测试最后一个生成的最小数值是否越界
                int idx = count - 1;
                if (idx.ToString().Length > Length)
                    throw new Exception("数量超出长度界限");
                //该数据长度下的最大值
                long maxV = Math.Pow(CharList.Length, Length) - 1 > long.MaxValue ? long.MaxValue : (long)(Math.Pow(CharList.Length, Length) - 1);
                if (maxV < idx)
                    throw new Exception();
                //m_span = (maxV - idx) / count;
                
//数据余量初始化
                m_span = maxV - idx; 
                //补齐字符初始化
                m_padStr = CharList.ToCharArray()[0];
                //初始化数据集合
                m_codes = null;
            }
            catch
            {
                throw new Exception("随机码起始值或生成数量越界!尝试调整生成数量、数据长度、起始字符串等设置后再试。");
            }
        }
        public void PrepareCodes(int count)
        {
            //m_codes = new List<string>(count);
            string[] source = new string[count];
            for (int i = 0; i < count; i++)
            {
                source[i] = GenerateCode(i, count);
            }
            m_codes = new List<string>(Shuffle<string>(source));
            source = null;
        }
        private IEnumerable<T> Shuffle<T>(IEnumerable<T> source)
        {
            m_ro = new Random();
            T[] elements = source.ToArray();
            for (int i = elements.Length - 1; i > 0; i--)
            {
                int swapIndex = m_ro.Next(i + 1);
                yield return elements[swapIndex];
                elements[swapIndex] = elements[i];
            }
            yield return elements[0];
        }
        private string GenerateCode(int index, int count)
        {
            long num2 = DateTime.Now.Ticks + index;
            m_ro = new Random(((int)(((ulong)num2) & 0xffffffffL)) | ((int)(num2 >> index)));
            //本次可以使用的最大余量
            long s = m_span / (count - index);            
            //本次使用的余量
            s = m_ro.Next(s + 1 > int.MaxValue ? int.MaxValue : (int)(s + 1));
            //余量减少
            m_span -= s;
            //记录最近一次使用的数值
            m_lastNum += 1 + s;
            long position = m_lastNum;
            StringBuilder sb = new StringBuilder();
            int yushu = 0;
            while (position >= CharList.Length)
            {
                yushu = (int)(position % CharList.Length);
                sb.Append(CharList.Substring(yushu, 1));
                position = (position - yushu) / CharList.Length;
            }
            sb.Append(CharList.Substring((int)position, 1));
            return (new string(sb.ToString().Reverse<char>().ToArray())).PadLeft(Length, m_padStr);
        }
        public void Dispose()
        {
            if(m_ro != null)
                m_ro = null;
            if (m_codes != null)
                m_codes = null;
        }
        public override string ToString()
        {
            return string.Format("<字符集:{0},长度:{1},起始:{2}>", CharList, Length, FromStr);
        }
    }
}