2015-11-02 89 views
0

我有一個數據表我用作中繼器的數據源,並希望每次調用它時都會按隨機順序顯示結果。c#Randomize DataTable rows

我已經能夠在檢索數據時做到這一點,但希望在綁定之前緩存結果集。

是否有人在綁定到中繼器之前將數據表的行進行隨機播放?

CODE:

 TreeProvider tp = new TreeProvider(); 
    DataSet ds = new DataSet(); 
    string sKey = "KEY"; 
    using (CachedSection<DataSet> cs = new CachedSection<DataSet>(ref ds, 5, true, null, sKey)) 
    { 
     if (cs.LoadData) 
     { 
     ds = tp.SelectNodes("", "URL", "", true, "DOCTYPE", "", "NewID()", -1, true, 5); 
     cs.Data = ds; 
     } 
    } 
    if (!DataHelper.DataSourceIsEmpty(ds)) 
    { 
     rprItems.DataSource = ds.Tables[0].DefaultView; 
     rprItems.DataBind(); 
    } 

任何指導被理解。

+1

你可以添加你到目前爲止問題的代碼嗎? – Sybren

+0

感覺沒有必要,因爲它是通用的。現在加入... – Spitfire2k6

+1

這裏有一個可能對你有幫助的鏈接https://social.msdn.microsoft.com/Forums/en-US/b832b9ff-5e1a-490f-bcf6-3e72070b5879/shuffle-datatable-rows – Sybren

回答

0

我最終採取的表的副本,添加一個字段,每個分配一個隨機數然後按該行排序。

 DataTable dt = ds.Tables[0].Copy(); 
     if (!dt.Columns.Contains("SortBy")) 
      dt.Columns.Add("SortBy", typeof (Int32)); 

     foreach (DataColumn col in dt.Columns) 
      col.ReadOnly = false; 

     Random rnd = new Random(); 
     foreach (DataRow row in dt.Rows) 
     { 
      row["SortBy"] = rnd.Next(1, 100); 
     } 
     DataView dv = dt.DefaultView; 
     dv.Sort = "SortBy"; 
     DataTable sortedDT = dv.ToTable(); 

     rprItems.DataSource = sortedDT; 
     rprItems.DataBind(); 
0

你可以嘗試這樣的事情,我知道這是不是漂亮,但:

DataTable newTable = new DataTable(); 
newTable.TableName = "<NewTableName>"; 
//Make a new Random generator 
Random rnd = new Random(); 
while (<new table length> != <old table length>) 
{ 
    //We'll use this to make sure we don't have a duplicate row 
    bool rowFound = false; 
    //index generation 
    int index = rnd.Next(0, <max number of rows in old data>); 
    //use the index on the old table to get the random data, then put it into the new table. 
    foreach (DataRow row in newTable.Rows) 
    { 
     if (oldTable.Rows[index] == row) 
     { 
      //Oops, there's duplicate data already in the new table. We don't want this. 
      rowFound = true; 
      break; 
     } 
    } 
    if (!rowFound) 
    { 
     //add the row to newTable 
     newTable.Rows.Add(oldTable.Rows[index]; 
    } 
} 

你將不得不使用,當然你自己的表,名稱,長度,但是這應該是確定使用。如果有很多數據,這可能需要一段時間。這是我能想到的最好的,而且沒有經過測試。我很想知道它是否有效。

+0

隨機類是僞隨機數發生器,它永遠不會創建真隨機數 –

+0

我不知道有任何其他方式做隨機。到目前爲止,每個答案都有類似的建議。 –

+0

檢查我的答案,它沒有,它參考了使用System.Cryptography –

0

你可以嘗試:

 DataTable dt = new DataTable(); 
     dt.Columns.Add("Name"); 
     dt.Columns.Add("Sort"); 
     dt.Rows.Add("TEST"); 
     dt.Rows.Add("TEST1"); 
     dt.Rows.Add("TEST2"); 

     var rnd = new Random(DateTime.Now.Millisecond); 
     foreach (DataRow row in dt.Rows) 
     { 
      row["Sort"] = rnd.Next(dt.Rows.Count); 
     } 


     var dv = new DataView(dt); 
     dv.Sort = "Sort"; 
     foreach (DataRowView row in dv) 
     { 
      Console.WriteLine(row[0]); 
     } 

如果你的數據表是不是太大,它應該這樣做。

+0

隨機類是僞隨機數發生器,它永遠不會創建真隨機數 –

+0

您可以替換任何你想要的。將排序列更改爲guid並生成新的Guid將執行與SQL相同的技巧。請記住,到目前爲止,我們不需要生成唯一的隨機數,這個想法就是隨機排序結果。保持簡單,除非你需要複雜的解決方案 – user1965927

0

這應是直線前進,據我能理解,讓我把它分解成部分:

  • 獲得一個包含DataTable用於直放站
  • 存儲原始DataSetDataSetCache
  • 取兩個索引,beginIndex as 0endIndex as DataSet.Tables[0].Rows.Count,beginIndex是包含的,endIndex是唯一的
  • 現在創建一系列隨機索引,使用以下Article,還檢查以下由Jon Skeet編制的detail,這使用System.Cryptography - RNGCryptoServiceProvider
  • 邏輯應該是這樣的,每次選擇一個新數字時,它被排除,直到所有數字串聯被選擇,檢查下面的代碼,其中一部分是從鏈接複製的上方設置:

    void Main() 
    { 
    List<int> newList = new List<int>(); 
    
    DataTable dt = new DataTable(); 
    
    int beginIndex = 0; 
    
    int endIndex = dt.Rows.Count; 
    
    int numberIndex = 0; 
    
    CustomRandom cr = new CustomRandom(); 
    
    while(numberIndex < dt.Rows.Count) 
    { 
        int randomNumber = cr.Next(beginIndex, endIndex);  
    
        if(newList.Contains(randomNumber)) 
        continue; 
        else 
        { 
         newList.Add(randomNumber); 
         numberIndex ++; 
        } 
    } 
    } 
    
    public class CustomRandom 
    { 
        private const int BufferSize = 1024; // must be a multiple of 4 
        private byte[] RandomBuffer; 
        private int BufferOffset; 
        private RNGCryptoServiceProvider rng; 
    
    public CustomRandom() 
    { 
        RandomBuffer = new byte[BufferSize]; 
        rng = new RNGCryptoServiceProvider(); 
        BufferOffset = RandomBuffer.Length; 
    } 
    
        private void FillBuffer() 
        { 
        rng.GetBytes(RandomBuffer); 
        BufferOffset = 0; 
        } 
    
        public int Next() 
        { 
        if (BufferOffset >= RandomBuffer.Length) 
        { 
         FillBuffer(); 
        } 
        int val = BitConverter.ToInt32(RandomBuffer, BufferOffset) & 
        0x7fffffff; 
        BufferOffset += sizeof(int); 
        return val; 
    } 
    public int Next(int maxValue) 
    { 
        return Next() % maxValue; 
    } 
    public int Next(int minValue, int maxValue) 
    { 
        if (maxValue < minValue) 
        { 
         throw new ArgumentOutOfRangeException("maxValue must be greater than or equal to minValue"); 
        } 
        int range = maxValue - minValue; 
        return minValue + Next(range); 
    } 
    public double NextDouble() 
    { 
        int val = Next(); 
        return (double)val/int.MaxValue; 
    } 
    public void GetBytes(byte[] buff) 
    { 
        rng.GetBytes(buff); 
    } 
    } 
    
    • 現在基於在列表newList產生的索引,創建一個新的DataTable,其可用於作爲的如下:

      DataTable randomTable = new DataTable(); 
      
          foreach(int randomIndex in newList) 
          { 
          randomTable.Rows.Add(dt.Rows[randomIndex]; 
          } 
      

    現在randomTable可以用作源Repeater

+0

不要使用隨機類,因爲它永遠不會生成真隨機數,總是使用True我已經在上面的代碼中建議的隨機數 –

+0

修改了代碼,現在CustomRandom僅初始化一次,而不是每一次while循環迭代,只需要一次初始化,就可以生成真正的隨機數 –