Is using Random and OrderBy a good shuffle algorithm?

前端 未结 12 1552
-上瘾入骨i
-上瘾入骨i 2020-11-21 11:41

I have read an article about various shuffle algorithms over at Coding Horror. I have seen that somewhere people have done this to shuffle a list:

var r = ne         


        
12条回答
  •  借酒劲吻你
    2020-11-21 12:27

    Startup time to run on code with clear all threads and cache every new test,

    First unsuccessful code. It runs on LINQPad. If you follow to test this code.

    Stopwatch st = new Stopwatch();
    st.Start();
    var r = new Random();
    List list = new List();
    list.Add(new String[] {"1","X"});
    list.Add(new String[] {"2","A"});
    list.Add(new String[] {"3","B"});
    list.Add(new String[] {"4","C"});
    list.Add(new String[] {"5","D"});
    list.Add(new String[] {"6","E"});
    
    //list.OrderBy (l => r.Next()).Dump();
    list.OrderBy (l => Guid.NewGuid()).Dump();
    st.Stop();
    Console.WriteLine(st.Elapsed.TotalMilliseconds);
    

    list.OrderBy(x => r.Next()) uses 38.6528 ms

    list.OrderBy(x => Guid.NewGuid()) uses 36.7634 ms (It's recommended from MSDN.)

    the after second time both of them use in the same time.

    EDIT: TEST CODE on Intel Core i7 4@2.1GHz, Ram 8 GB DDR3 @1600, HDD SATA 5200 rpm with [Data: www.dropbox.com/s/pbtmh5s9lw285kp/data]

    using System;
    using System.Runtime;
    using System.Diagnostics;
    using System.IO;
    using System.Collections.Generic;
    using System.Collections;
    using System.Linq;
    using System.Threading;
    
    namespace Algorithm
    {
        class Program
        {
            public static void Main(string[] args)
            {
                try {
                    int i = 0;
                    int limit = 10;
                    var result = GetTestRandomSort(limit);
                    foreach (var element in result) {
                        Console.WriteLine();
                        Console.WriteLine("time {0}: {1} ms", ++i, element);
                    }
                } catch (Exception e) {
                    Console.WriteLine(e.Message);
                } finally {
                    Console.Write("Press any key to continue . . . ");
                    Console.ReadKey(true);
                }
            }
    
            public static IEnumerable GetTestRandomSort(int limit)
            {
                for (int i = 0; i < 5; i++) {
                    string path = null, temp = null;
                    Stopwatch st = null;
                    StreamReader sr = null;
                    int? count = null;
                    List list = null;
                    Random r = null;
    
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                    Thread.Sleep(5000);
    
                    st = Stopwatch.StartNew();
                    #region Import Input Data
                    path = Environment.CurrentDirectory + "\\data";
                    list = new List();
                    sr = new StreamReader(path);
                    count = 0;
                    while (count < limit && (temp = sr.ReadLine()) != null) {
    //                  Console.WriteLine(temp);
                        list.Add(temp);
                        count++;
                    }
                    sr.Close();
                    #endregion
    
    //              Console.WriteLine("--------------Random--------------");
    //              #region Sort by Random with OrderBy(random.Next())
    //              r = new Random();
    //              list = list.OrderBy(l => r.Next()).ToList();
    //              #endregion
    
    //              #region Sort by Random with OrderBy(Guid)
    //              list = list.OrderBy(l => Guid.NewGuid()).ToList();
    //              #endregion
    
    //              #region Sort by Random with Parallel and OrderBy(random.Next())
    //              r = new Random();
    //              list = list.AsParallel().OrderBy(l => r.Next()).ToList();
    //              #endregion
    
    //              #region Sort by Random with Parallel OrderBy(Guid)
    //              list = list.AsParallel().OrderBy(l => Guid.NewGuid()).ToList();
    //              #endregion
    
    //              #region Sort by Random with User-Defined Shuffle Method
    //              r = new Random();
    //              list = list.Shuffle(r).ToList();
    //              #endregion
    
    //              #region Sort by Random with Parallel User-Defined Shuffle Method
    //              r = new Random();
    //              list = list.AsParallel().Shuffle(r).ToList();
    //              #endregion
    
                    // Result
    //              
                    st.Stop();
                    yield return st.Elapsed.TotalMilliseconds;
                    foreach (var element in list) {
                    Console.WriteLine(element);
                }
                }
    
            }
        }
    }
    

    Result Description: https://www.dropbox.com/s/9dw9wl259dfs04g/ResultDescription.PNG
    Result Stat: https://www.dropbox.com/s/ewq5ybtsvesme4d/ResultStat.PNG

    Conclusion:
    Assume: LINQ OrderBy(r.Next()) and OrderBy(Guid.NewGuid()) are not worse than User-Defined Shuffle Method in First Solution.

    Answer: They are contradiction.

提交回复
热议问题