C#批量產生大資料量無重複隨機資料的另類高效實現

來源:互聯網
上載者:User

註:本文思路已經應用於“飛梭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);
        }
    }
}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.