Randomizing a list of chars in a string, C# - c#

I've been playing around / researching ways to randomize the order of chars in a string. I frankly just don't understand how to do it. I've searched through the C# documentation and a handful of websites. I found one particular way of randomizing the order of chars in a string but I don't understand how it works. I've also read that the Random class isn't truly random, which would explain why the results are so similar.
How exactly does the current method I'm using function (especially the OrderBy() method).
Is there a better way to do this?
Current code
string baseList = "abcdefghijklmnopqrstuvwxyz";
Random random = new Random();
string[] randLists = new string[baseList.Length];
for (int i = 0; i < baseList.Length; i++)
{
randLists[i] = new string(baseList.ToCharArray().OrderBy(s => (random.Next(2) % 2) == 0).ToArray());
Console.WriteLine(randLists[i]);
}
Console.Read();
This is my attempt at randomizing but it doesn't function at all:
*string bL = "abcdefghijklmnopqrstuvwxyz";
string[] rL = new string[bL.Length];
Random randomizer = new Random();
for (int i = 0; i < bL.Length; i++)
{
rL = new string(bL.ToCharArray().OrderBy(c => (randomizer.Next(0, 25)).ToString()));
}*
Thanks in advance for any assistance. I'll continue researching in the meantime.

Although the code that you found is short, it does not make a nicely distributed shuffle of the original string: the randomizer is likely to give you the same numbers in the process of generating a shuffle, increasing a probability that the corresponding characters would remain in the same order relative to each other as in your original string.
One solution to this problem is using Fisher–Yates shuffle. It is easy to implement (you need to stay away from common implementation errors, though).
Since string is immutable, you would need to shuffle an array of characters, and then make a string from it.

To add to the suggestion of the Fisher-Yates shuffle, here's a code sample, just ignore the test assertion, just trying to debug and make sure it's random enough.
[TestMethod]
public void RandomizeText()
{
string baseList = "abcdefghijklmnopqrstuvwxyz";
char[] result = baseList.ToCharArray();
Shuffle<char>(result);
var final = string.Join("", result);
final.Should().NotMatch(baseList);
}
public void Shuffle<T>(T[] array)
{
var random = new Random();
for (int x = 0; x < 100; x++)
{
for (int i = array.Length; i > 1; i--)
{
// Pick random element to swap.
int j = random.Next(i); // 0 <= j <= i-1
// Swap.
T tmp = array[j];
array[j] = array[i - 1];
array[i - 1] = tmp;
}
}
}

Another example...
static void Main(string[] args)
{
string baseList = "abcdefghijklmnopqrstuvwxyz";
Console.WriteLine(baseList);
string shuffled = Shuffle(baseList);
Console.WriteLine(shuffled);
Console.ReadLine();
}
static Random R = new Random();
static string Shuffle(string list)
{
int index;
List<char> chars = new List<char>(list);
StringBuilder sb = new StringBuilder();
while (chars.Count > 0)
{
index = R.Next(chars.Count);
sb.Append(chars[index]);
chars.RemoveAt(index);
}
return sb.ToString();
}

Related

C# - Random output from array to textbox

I'm kinda new to array and I made a char array (with 174 things in it) but I don't know how to output it in a randomize way. I'm trying to make a secured code for my system. I wanted to output 13 char from that 174 char array into a textbox, but I don't think I get the logic. Thank you in advance! Here is the code that only outputs 1 char per button click:
Random rnd = new Random();
int randomnum = rnd.Next(0, 174);
for (int x = 0; x <= 13; x++)
{
textBox11.Text = chararray[randomnum];
}
Your code is almost there, but there are a few issues:
You need to append the new character to the end of the string as apposed to just setting the Text value directly. You can do this easily with += instead of =.
You need to pick a different random character for each iteration of the loop, so move your call to .Next inside the for.
Putting this together you'd have something like this:
Random rnd = new Random();
for (int x = 0; x <= 13; x++)
{
int randomnum = rnd.Next(0, 174);
textBox11.Text += chararray[randomnum];
}
Note however, that if this is for the purpose of security, using Random isn't great. You should probably use something like the RNGCryptoServiceProvider. For example:
using (var rng = new RNGCryptoServiceProvider())
{
byte[] password = new byte[10];
rng.GetBytes(password);
textBox11.Text = Convert.ToBase64String(password).Remove(13);
}
I've attached a screenshot of this code working. I had a small typo
This will change the seed for random
int seed = 1;
Create an instance of Random, we don't need to recreate it every time we need to use it
Random r = new Random(seed);
This only initializes the characters
char[] _myChars = new char[170];
for(var i = 0; i < _myChars.Length; i++)
{
_myChars[i] = (char)(i%26 + 65);
}
This is the query you're looking for, it will query the characters and order them by a random order with r.Next()
var output = _myChars.OrderBy(o => r.Next()).Take(13).ToList();
This is only for displaying the output, you would want to use the output in your textbox
for(var i = 0; i < output.Count; i++)
{
Console.WriteLine(output[i]);
}
Console.ReadLine();

c# Read 'n' amount of random lines from txt file

I am attempting to read (n) amount of random lines from a text file with about 200 entries (lines) and populate a listbox called "recSongs". I have provided some simple code which retrieves one random line from the text file, but I want retrieve n amount.
Here is my code.
var lines = File.ReadAllLines(#"file.txt");
var r = new Random();
var randomLineNumber = r.Next(0, lines.Length - 1);
var line = lines[randomLineNumber];
recSongs.Items.Add(line);
How about:
var lines = File.ReadAllLines("file.txt").OrderBy(x => Guid.NewGuid()).Take(n);
n will be the input , i.e no of lines you need
List <string> text = File.ReadLines("file.txt").Take(n).ToList();
Edit
If you need random lines, you could do,
string[] lines = File.ReadAllLines(#"C:\YourFile.txt");
List<string> source = new List<string>();
int n = 10;
for (int i = 0; i < n; i++)
{
source.Add(lines[new Random().Next(lines.Length)]);
}
var lines = File.ReadAllLines(#"file.txt");
var r = new Random();
var randomized = lines.OrderBy(item => r.Next()); //randomize the list
recSongs.Items.AddRange(randomized.Take(N).ToArray()); //Add N amount to listbox
This solution also avoids duplicate randoms
Probably the easiest way, though not the most memory-efficient, is to slurp the file into an in-memory collection of its lines, then Shuffle() the lines and take however many you want:
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> input)
{
var buffer = input.ToArray();
//Math.Random is OK for "everyday" randomness;
//use RNGCryptoServiceProvider if you need
//cryptographically-strong randomness
var rand = new Random();
//As the loop proceeds, the element to output will be randomly chosen
//from the elements at index i or above, which will then be swapped
//with i to get it out of the way; the yield return gives us each
//shuffled value as it is chosen, and allows the shuffling to be lazy.
for (int i = 0; i < buffer.Length; i++)
{
int j = rand.Next(i, buffer.Length);
yield return buffer[j];
//if we cared about the elements in the buffer this would be a swap,
//but we don't, so...
buffer[j] = buffer[i];
}
}
...
string[] fileLines = GetLinesFromFile(fileName); //a StreamReader makes this pretty easy
var randomLines = fileLines.Shuffle().Take(n);
Some notes:
This should work fairly well for a text file of about 200 lines; beyond a couple hundred thousand lines, you'll start having memory problems. A more scalable solution would be to shuffle an array of line numbers, then use those to seek for and read the specific lines you want, discarding all the others.
This solution produces the random lines in random order. If you want to preserve the order of the lines from the file, do the line-number variant, sorting the line numbers you select, then just keep the lines in that order after reading them out of the file.
Try this
var lines = File.ReadAllLines(#"file.txt");
var r = new Random();
int noLines = 10;// n lines
for (int i = 0; i < noLines; i++)
{
var randomLineNumber = r.Next(0, lines.Length - 1);
var line = lines[randomLineNumber];
recSongs.Items.Add(line);
}
You could do something like:
HashSet<int> linesHash = new HashSet<int>();
var lines = file.ReadLines();
for (int i = 0; i < numLinesToGet; i++)
{
int line=0;
do
{
line = rand.Next(0, lines.Length);
}while(linesHash.Contains(line));
linesHash.Add(line);
linesAdded.Add(lines[line]);
}
Note that if the amount of lines to get is greater than the actually number of lines my code would never end, so some checks must be done prior to execute the for loop.
This will add numLines random lines to your collection. Note that there is a chance that there will be duplicates.
var lines = File.ReadAllLines(#"file.txt");
var r = new Random();
int numLines = 5;
for (int i = 0; i < numLines; i++)
{
recSongs.Items.Add(lines[r.Next(0, lines.Length - 1)]);
}
To enforce unique items, you could do something like this:
for (int i = 0; i < numLines; i++)
{
var randomItem = string.Empty;
do
{
randomItem = lines[r.Next(0, lines.Length - 1)];
} while (recSongs.Contains(randomItem));
recSongs.Items.Add(randomItem);
}
But now note that it is possible that it will never exit. The joys of Random!
var lines = File.ReadAllLines(#"file.txt");
var random = new Random();
var lines = Enumerable.Repeat( -1, n ) // -1 is a filler and is discarded by the select.
.Select( _ => random.Next(0, lines.Length - 1 ) )
.Select( index => lines[index] );
foreach( var line in lines )
{
recSongs.Items.Add(line);
}

Adding specific numbers from one sequence to another

I feel like this task should not be done this way...
My sequenceY length is not equal to number of steam numbers because you can't assign int[] length with int that have 0 as a starting value.
Therefore my sequenceY have a lot of 0 inside and I can't print the whole sequence. I even tried adding this after for loop:
sequenceY = new int[steamnumbercounter];
But it didn't work ... Why ?
My other question is how do programmers deal with sequences that have unknown length?
I managed to print only steam numbers but the task says print sequenceY not only part of it.
// 4. sequenceX[20] is made of random numbers from 1 to 30 ,
// sequenceY is made of steam numbers from sequenceX. Print sequneceY.
int[] nizx = new int[20];
int[] nizy = new int[20];
int n = 0;
int steamnumbercounter = 0;
Random rnd = new Random();
for (int i = 0; i < nizx.Length; i++)
{
nizx[i] = rnd.Next(1, 30);
if (nizx[i]%2==0)
{
nizy[n] = nizx[i];
n++;
steamnumbercounter++;
}
Console.Write("{0} , ", nizx[i]);
}
for (int i = 0; i < steamnumbercounter; i++)
{
Console.WriteLine("{0} , ",nizy[i]);
}
Partial code review along with an answer.
But it didn't work ... Why ?
That code didn't work because you're reassigning sequenceY to a completely new value.
My other question is how do programmers deal with sequences that have unknown length?
So, with that known we can do a few things here: create an array and use Array.Resize, use a List<T>, fill the initial array then swap it for one of the right size which is filled.
I'm going to assume a "steam" number is an even one.
Your naming is not good: nizx and nizy don't convey the meaning or line up with the problem.
I'm going to demonstrate the last option (since you stated that you don't know how to use many of the moderately complex parts of .NET in this class yet, which is fine): fill the initial array and swap it for a new one. This will run in O(n^2) time (sorta).
So, let's start with our source array.
int[] sequenceX = new int[20];
Next we'll define our destination array to be the same size as our source array. (This is the maximum number of values that could be stored in it, we'll shrink it later.)
int[] sequenceY = new int[sequenceX.Length];
Then we need a variable to hold how many numbers we found that meet our criteria:
int steamNumbers = 0;
And lastly, our Random.
Random random = new Random();
Then, we look through all our sequenceX as you did, but we'll update the logic a bit.
for (int i = 0; i < sequenceX.Length; i++)
{
sequenceX[i] = random.Next(1, 30);
if (sequenceX[i] % 2 == 0)
{
sequenceY[steamNumbers] = sequenceX[i];
steamNumbers++;
}
}
So our code looks almost the same as yours, but we have one more thing to do: since you only want sequenceY to contain steamNumbers we have to shrink it or something.
int[] tempSequenceY = sequenceY;
sequenceY = new int[steamNumbers];
for (int i = 0; i < steamNumbers; i++)
{
sequenceY[i] = tempSequenceY[i];
}
Now sequenceY only has your steam numbers in it.
Final code:
int[] sequenceX = new int[20];
int[] sequenceY = new int[sequenceX.Length];
int steamNumbers = 0;
Random random = new Random();
for (int i = 0; i < sequenceX.Length; i++)
{
sequenceX[i] = random.Next(1, 30);
if (sequenceX[i] % 2 == 0)
{
sequenceY[steamNumbers] = sequenceX[i];
steamNumbers++;
}
}
int[] tempSequenceY = sequenceY;
sequenceY = new int[steamNumbers];
for (int i = 0; i < steamNumbers; i++)
{
sequenceY[i] = tempSequenceY[i];
}
// Print your `sequenceY` here.
You could extract this to a method pretty easily as well:
public int[] GetSteamNumbers(int sequenceCount, int randomMinimum, int randomMaximum)
{
int[] sequenceX = new int[sequenceCount];
int[] sequenceY = new int[sequenceX.Length];
int steamNumbers = 0;
Random random = new Random();
for (int i = 0; i < sequenceX.Length; i++)
{
sequenceX[i] = random.Next(randomMinimum, randomMaximum);
if (sequenceX[i] % 2 == 0)
{
sequenceY[steamNumbers] = sequenceX[i];
steamNumbers++;
}
}
int[] tempSequenceY = sequenceY;
sequenceY = new int[steamNumbers];
for (int i = 0; i < steamNumbers; i++)
{
sequenceY[i] = tempSequenceY[i];
}
return sequenceY;
}
And then call it with:
int[] steamNumbers = GetSteamNumbers(20, 1, 30);
Of course, for the more advanced users (this doesn't help you, but it may help others) we can do something as follows using LINQ:
var random = new Random();
var sequenceY = Enumerable.Range(1, 20)
.Select(x => random.Next(1, 30))
.Where(x => x % 2 == 0)
.ToArray();
Which should have the same effect. (Just demonstrating that there are still things in C# to look forward to in the future.)
Disclaimer: I wrote this entire answer outside of the IDE and without actually compiling it, I make no guarantees to the accuracy of the code but the procedure itself should be fairly straight forward.
The thing with arrays in C# is that they are of fixed size.
You'll have to iterate through and re-create it or use a IEnumerable that has dynamic sizes, such as Lists.
Solution here would be to use a List that contains your integers and then you would use nizx.Add(rnd.Next(1, 30));
Elaborating on my comment above: You can create a 'fake' list by concatenating the values you need in a string, separated by commas. The string.Split(',') will give you the resulting array that you need.
Given a string of form "a,b,c,d" string.Split(',') will create the array ["a","b,"c","d"]. The code:
{
int[] nizx = new int[20];
string numberString = string.Empty;
int n = 0;
Random rnd = new Random();
for (int i = 0; i < nizx.Length; i++)
{
nizx[i] = rnd.Next(1, 30);
if (nizx[i] % 2 == 0)
{
numberString += nizx[i] + ",";
n++;
}
}
var numberArray = numberString.Split(',');
for (int i = 0; i < n; i++)
{
Console.WriteLine("{0} , ", numberArray[i]);
}
}

A Faster Way To Reverse A String? [duplicate]

This question already has answers here:
Best way to reverse a string
(51 answers)
Closed 9 years ago.
Below is the fastest code I could create for reversing a String
public static void ReverseFast(string x)
{
string text = x;
StringBuilder reverse = new StringBuilder();
for (int i = text.Length - 1; i >= 0; i--)
{
reverse.Append(text[i]);
}
Console.WriteLine(reverse);
}
I want to address every bottleneck in this equation to make it as fast as possible. The only one I can find so far is the Array Bounds check which I only partially understand. Is there anyway to disable this as I understand it if you use .Length the compiler decides not to check the bounds but if you are decrementing as I am in the for loop it still does the boundary check? Can someone convert this to use pointers for me which would avoid the boundary check, I would like to test the speed difference for strings in the range of 100k+ characters.
Based on the comments and posts below this is what I have come up with so far.
public static void ReverseFast(string x)
{
StringBuilder reverse = new StringBuilder(x.Length);
for (int i = x.Length - 1; i >= 0; i--)
{
reverse.Append(x[i]);
}
Console.WriteLine(reverse);
}
This above solution is way faster than the suggested duplicate question answer. This question is really addressing reversal in the range of 5000 * 26 characters +. I would still like to test this out using pointers to really see if there is no bottleneck especially with such large amount of characters.
var arr = x.ToCharArray();
Array.Reverse(arr);
return new string(arr);
Note, however, that this will reverse any unicode modifier characters (accents, etc).
Benchmark:
Array.Reverse: 179ms
StringBuilder: 475ms
With:
static void Main()
{
string text = new string('x', 100000);
GC.Collect();
GC.WaitForPendingFinalizers();
var watch = Stopwatch.StartNew();
const int LOOP = 1000;
for (int i = 0; i < LOOP; i++)
{
var arr = text.ToCharArray();
Array.Reverse(arr);
string y = new string(arr);
}
watch.Stop();
Console.WriteLine("Array.Reverse: {0}ms", watch.ElapsedMilliseconds);
GC.Collect();
GC.WaitForPendingFinalizers();
watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
var reverse = new StringBuilder(text.Length);
for (int j = text.Length - 1; j >= 0; j--)
{
reverse.Append(text[j]);
}
string y = reverse.ToString();
}
watch.Stop();
Console.WriteLine("StringBuilder: {0}ms", watch.ElapsedMilliseconds);
}
If we try a string of length 500 and loop 500000 times:
Array.Reverse: 480ms
StringBuilder: 1176ms
I also tried adding unsafe into that, i.e.
fixed (char* c = text)
{
for (int j = text.Length - 1; j >= 0; j--)
{
reverse.Append(c[j]);
}
}
this made no difference whatsoever.
And I added in JeffRSon's answer too; I get:
Array.Reverse: 459ms
StringBuilder: 1092ms
Pointer: 513ms
(for the 500 length x 5000 iterations test)
Here's a pointer based solution:
unsafe String Reverse(String s)
{
char[] sarr = new char[s.Length];
int idx = s.Length;
fixed (char* c = s)
{
char* c1 = c;
while (idx != 0)
{
sarr[--idx] = *c1++;
}
}
return new String(sarr);
}
Getting rid of the array index (sarr[--idx]) the following might be faster:
unsafe String Reverse(String s)
{
char[] sarr = new char[s.Length];
fixed (char* c = s)
fixed (char* d = sarr)
{
char* c1 = c;
char* d1 = d + s.Length;
while (d1 > d)
{
*--d1 = *c1++;
}
}
return new String(sarr);
}
Set the capacity when you create the StringBuilder, that way it doesn't have to grow during the loop and allocate more memory. Assigning the parameter to a local variable is an unnecessary step, as the parameter is already a local variable.
public static void ReverseFast(string text) {
StringBuilder reverse = new StringBuilder(text.Length);
for (int i = text.Length - 1; i >= 0; i--) {
reverse.Append(text[i]);
}
}
That is just the basic steps to remove any unneccesary work. If you really have a performance problem with the code, you would need to analyse what the generated code does, and possibly create different versions that do different things depending on the current framework and hardware.

Most efficient way to randomly "sort" (Shuffle) a list of integers in C#

I need to randomly 'sort' a list of integers (0-1999) in the most efficient way possible. Any ideas?
Currently, I am doing something like this:
bool[] bIndexSet = new bool[iItemCount];
for (int iCurIndex = 0; iCurIndex < iItemCount; iCurIndex++)
{
int iSwapIndex = random.Next(iItemCount);
if (!bIndexSet[iSwapIndex] && iSwapIndex != iCurIndex)
{
int iTemp = values[iSwapIndex];
values[iSwapIndex] = values[iCurIndex];
values[iCurIndex] = values[iSwapIndex];
bIndexSet[iCurIndex] = true;
bIndexSet[iSwapIndex] = true;
}
}
A good linear-time shuffling algorithm is the Fisher-Yates shuffle.
One problem you'll find with your proposed algorithm is that as you near the end of the shuffle, your loop will spend a lot of time looking for randomly chosen elements that have not yet been swapped. This may take an indeterminate amount of time once it gets to the last element to swap.
Also, it looks like your algorithm will never terminate if there are an odd number of elements to sort.
static Random random = new Random();
public static IEnumerable<T> RandomPermutation<T>(IEnumerable<T> sequence)
{
T[] retArray = sequence.ToArray();
for (int i = 0; i < retArray.Length - 1; i += 1)
{
int swapIndex = random.Next(i, retArray.Length);
if (swapIndex != i) {
T temp = retArray[i];
retArray[i] = retArray[swapIndex];
retArray[swapIndex] = temp;
}
}
return retArray;
}
modified to handle lists or other objects implementing IEnumerable
We can make an extension method out of this to get a Random enumerator for any IList collection
class Program
{
static void Main(string[] args)
{
IList<int> l = new List<int>();
l.Add(7);
l.Add(11);
l.Add(13);
l.Add(17);
foreach (var i in l.AsRandom())
Console.WriteLine(i);
Console.ReadLine();
}
}
public static class MyExtensions
{
public static IEnumerable<T> AsRandom<T>(this IList<T> list)
{
int[] indexes = Enumerable.Range(0, list.Count).ToArray();
Random generator = new Random();
for (int i = 0; i < list.Count; ++i )
{
int position = generator.Next(i, list.Count);
yield return list[indexes[position]];
indexes[position] = indexes[i];
}
}
}
This uses a reverse Fisher-Yates shuffle on the indexes of the list we want to randomly enumerate through. Its a bit of a size hog (allocating 4*list.Count bytes), but runs in O(n).
As Greg pointed out the Fisher-Yates shuffle would be the best approach. Here is an implementation of the algorithm from Wikipedia:
public static void shuffle (int[] array)
{
Random rng = new Random(); // i.e., java.util.Random.
int n = array.length; // The number of items left to shuffle (loop invariant).
while (n > 1)
{
int k = rng.nextInt(n); // 0 <= k < n.
n--; // n is now the last pertinent index;
int temp = array[n]; // swap array[n] with array[k] (does nothing if k == n).
array[n] = array[k];
array[k] = temp;
}
}
The implementation above relies on
Random.nextInt(int) providing
sufficiently random and unbiased
results
I am not sure of the efficiency factor, but I have used something similar to the following, if you aren't opposed to using an ArrayList:
private ArrayList ShuffleArrayList(ArrayList source)
{
ArrayList sortedList = new ArrayList();
Random generator = new Random();
while (source.Count > 0)
{
int position = generator.Next(source.Count);
sortedList.Add(source[position]);
source.RemoveAt(position);
}
return sortedList;
}
Using this, you do not have to worry about the intermediate swapping.
To improve your efficiency you can keep a set of values/indices that have been swapped rather than a boolean for indicating they were swapped. Pick your randomized swap index from the remaining pool. When the pool is 0, or when you made it through the initial list then you are done. You don't have the potential to try to select a random swap index value.
When you do a swap, just remove them from the pool.
For the size of data you are looking at it is no big deal.
itemList.OrderBy(x=>Guid.NewGuid()).Take(amount).ToList()
ICR's answer is very fast, but the resulting arrays aren't distributed normally. If you want a normal distribution, here's the code:
public static IEnumerable<T> RandomPermutation<T>(this IEnumerable<T> sequence, int start,int end)
{
T[] array = sequence as T[] ?? sequence.ToArray();
var result = new T[array.Length];
for (int i = 0; i < start; i++)
{
result[i] = array[i];
}
for (int i = end; i < array.Length; i++)
{
result[i] = array[i];
}
var sortArray=new List<KeyValuePair<double,T>>(array.Length-start-(array.Length-end));
lock (random)
{
for (int i = start; i < end; i++)
{
sortArray.Add(new KeyValuePair<double, T>(random.NextDouble(), array[i]));
}
}
sortArray.Sort((i,j)=>i.Key.CompareTo(j.Key));
for (int i = start; i < end; i++)
{
result[i] = sortArray[i - start].Value;
}
return result;
}
Note that in my tests, this algorithm was 6 times slower than the one ICR provided, however this is the only way I could come up with to get a normal result distribution
Wouldn't something like this work?
var list = new[]{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
var random = new Random();
list.Sort((a,b)=>random.Next(-1,1));
what about :
System.Array.Sort(arrayinstance, RandomizerMethod);
...
//any evoluated random class could do it !
private static readonly System.Random Randomizer = new System.Random();
private static int RandomizerMethod<T>(T x, T y)
where T : IComparable<T>
{
if (x.CompareTo(y) == 0)
return 0;
return Randomizer.Next().CompareTo(Randomizer.Next());
}
voila!
Here is what I used.
This is surely not the fastest one, but it is probably good enough for most cases and most importantly, it is very simple.
IEnumerable<ListItem> list = ...;
Random random = new Random(); // important to not initialize a new random in the OrderBy() function
return list.OrderBy(i => random.Next());
You can use a NuGet package called ListShuffle (source code) to shuffle a list in a thread-safe way using the Fisher-Yates algorithm, with optional cryptographically-strong random.
var myList = new List<string>();
myList.Add("Item A");
myList.Add("Item B");
myList.Add("Item C");
myList.Shuffle();
or (less performant but cryptographically-strong)
var myList = new List<string>();
myList.Add("Item A");
myList.Add("Item B");
myList.Add("Item C");
myList.CryptoStrongShuffle();
I made a method using a temporary Hashtable, allowing the Hashtable's natural key sort to randomize. Simply add, read and discard.
int min = 1;
int max = 100;
Random random;
Hashtable hash = new Hashtable();
for (int x = min; x <= max; x++)
{
random = new Random(DateTime.Now.Millisecond + x);
hash.Add(random.Next(Int32.MinValue, Int32.MaxValue), x);
}
foreach (int key in hash.Keys)
{
HttpContext.Current.Response.Write("<br/>" + hash[key] + "::" + key);
}
hash.Clear(); // cleanup

Categories

Resources