C# 使用.NET随机化数组的最佳方法
使用.NET随机化字符串数组的最佳方法是什么?我的数组包含大约500个字符串,我想用相同的字符串创建一个新的C# 使用.NET随机化数组的最佳方法,c#,.net,algorithm,sorting,random,C#,.net,Algorithm,Sorting,Random,使用.NET随机化字符串数组的最佳方法是什么?我的数组包含大约500个字符串,我想用相同的字符串创建一个新的数组,但顺序是随机的 请在答案中包含一个C#示例。生成一个相同长度的随机浮点或整数数组。对该阵列排序,并在目标阵列上执行相应的交换 这将产生一个真正独立的排序。随机化数组是一项密集的工作,因为您必须在一组字符串之间移动。为什么不从数组中随机读取呢?在最坏的情况下,您甚至可以使用getNextString()创建包装器类。如果您确实需要创建一个随机数组,那么您可以执行以下操作 for i =
数组
,但顺序是随机的
请在答案中包含一个C#示例。生成一个相同长度的随机浮点或整数数组。对该阵列排序,并在目标阵列上执行相应的交换
这将产生一个真正独立的排序。随机化数组是一项密集的工作,因为您必须在一组字符串之间移动。为什么不从数组中随机读取呢?在最坏的情况下,您甚至可以使用getNextString()创建包装器类。如果您确实需要创建一个随机数组,那么您可以执行以下操作
for i = 0 -> i= array.length * 5
swap two strings in random places
*5是任意的 该算法简单但效率不高,O(N2)。所有的“orderby”算法通常都是O(N logn)。在数十万个元素下面,它可能不会有什么不同,但对于大型列表来说会有不同
var stringlist = ... // add your values to stringlist
var r = new Random();
var res = new List<string>(stringlist.Count);
while (stringlist.Count >0)
{
var i = r.Next(stringlist.Count);
res.Add(stringlist[i]);
stringlist.RemoveAt(i);
}
var stringlist=…//将您的值添加到stringlist
var r=新的随机变量();
var res=新列表(stringlist.Count);
而(stringlist.Count>0)
{
var i=r.Next(stringlist.Count);
res.Add(stringlist[i]);
stringlist.RemoveAt(i);
}
O(N2)的原因很微妙:是O(N)操作,除非您从末尾按顺序删除。如果您在.NET 3.5上,您可以使用以下IEnumerable coolness:
Random rnd=new Random();
string[] MyRandomArray = MyArray.OrderBy(x => rnd.Next()).ToArray();
编辑:下面是相应的VB.NET代码:
Dim rnd As New System.Random
Dim MyRandomArray = MyArray.OrderBy(Function() rnd.Next()).ToArray()
第二次编辑,回应System.Random由于返回基于时间的序列而“不线程安全”和“仅适用于玩具应用程序”的评论:在我的示例中,Random()是完全线程安全的,除非您允许重新输入随机数组的例程,在这种情况下,您需要类似于锁的东西(MyRandomArray)
为了不损坏您的数据,这将保护rnd
另外,应该很好地理解System.Random作为熵的来源不是很强。如中所述,如果您正在做任何与安全相关的事情,您应该使用源自System.Security.Cryptography.RandomNumberGenerator的内容。例如:
using System.Security.Cryptography;
只要想一想,你就可以做到:
public string[] Randomize(string[] input)
{
List<string> inputList = input.ToList();
string[] output = new string[input.Length];
Random randomizer = new Random();
int i = 0;
while (inputList.Count > 0)
{
int index = r.Next(inputList.Count);
output[i++] = inputList[index];
inputList.RemoveAt(index);
}
return (output);
}
public string[]随机化(string[]输入)
{
List inputList=input.ToList();
string[]输出=新字符串[input.Length];
随机随机发生器=新随机();
int i=0;
而(inputList.Count>0)
{
int index=r.Next(inputList.Count);
输出[i++]=输入列表[索引];
inputList.RemoveAt(索引);
}
返回(输出);
}
Random r=new Random();
列表=新列表(原始阵列);
List randomStrings=新列表();
而(list.Count>0)
{
int i=r.Random(list.Count);
添加(列表[i]);
列表。删除(i);
}
您正在寻找一种洗牌算法,对吗
好的,有两种方法可以做到这一点:聪明的人,但人们似乎总是误解它,把它弄错了,所以也许它并没有那么聪明,和愚蠢的石头,但谁在乎,因为它的工作方式
哑道
- 创建第一个数组的副本,但应使用随机数标记每个字符串
- 根据随机数对重复数组进行排序
- 无所事事
- (递归步骤)洗牌数组的前n-1个元素
- 选择范围为[0..n-1]的随机索引x
- 将索引n-1处的元素与索引x处的元素交换
时间复杂度为O(n)。以下是使用OLINQ的简单方法:
// Input array
List<String> lst = new List<string>();
for (int i = 0; i < 500; i += 1) lst.Add(i.ToString());
// Output array
List<String> lstRandom = new List<string>();
// Randomize
Random rnd = new Random();
lstRandom.AddRange(from s in lst orderby rnd.Next(100) select s);
//输入数组
List lst=新列表();
对于(inti=0;i<500;i+=1)lst.Add(i.ToString());
//输出阵列
List lstRandom=新列表();
//随机化
随机rnd=新随机();
lstRandom.AddRange(从RST orderby rnd中的s开始。下一步(100)选择s);
下面的实现使用了AKA-Knuth-Shuffle。它在O(n)时间内运行,并在适当的位置执行洗牌,因此比“按随机排序”技术性能更好,尽管它的代码行数更多。请参阅以获取一些比较性能度量。我使用了System.random,这对于非加密目的来说是很好的*
static class RandomExtensions
{
public static void Shuffle<T> (this Random rng, T[] array)
{
int n = array.Length;
while (n > 1)
{
int k = rng.Next(n--);
T temp = array[n];
array[n] = array[k];
array[k] = temp;
}
}
}
*对于较长的阵列,为了使(非常大的)置换数具有相同的可能性,有必要运行伪随机数生成器(PRNG)每次交换都要经过多次迭代以产生足够的熵。对于500个元素的数组,使用PRNG只能获得可能的500!置换中的一小部分。然而,Fisher-Yates算法是无偏的,因此洗牌将与您使用的RNG一样好。Jacco,您的解决方案是自定义的IComparer不安全。排序例程要求比较器符合多个要求才能正常运行。其中第一个要求是一致性。如果对同一对对象调用比较器,它必须始终返回相同的结果。(比较也必须是可传递的) 未能满足这些要求可能会导致排序例程中出现许多问题,包括无限循环的可能性 关于关联的解决方案
Random r = new Random();
List<string> list = new List(originalArray);
List<string> randomStrings = new List();
while(list.Count > 0)
{
int i = r.Random(list.Count);
randomStrings.Add(list[i]);
list.RemoveAt(i);
}
// Input array
List<String> lst = new List<string>();
for (int i = 0; i < 500; i += 1) lst.Add(i.ToString());
// Output array
List<String> lstRandom = new List<string>();
// Randomize
Random rnd = new Random();
lstRandom.AddRange(from s in lst orderby rnd.Next(100) select s);
static class RandomExtensions
{
public static void Shuffle<T> (this Random rng, T[] array)
{
int n = array.Length;
while (n > 1)
{
int k = rng.Next(n--);
T temp = array[n];
array[n] = array[k];
array[k] = temp;
}
}
}
var array = new int[] {1, 2, 3, 4};
var rng = new Random();
rng.Shuffle(array);
rng.Shuffle(array); // different order from first call to Shuffle
namespace System
{
public static class MSSystemExtenstions
{
private static Random rng = new Random();
public static void Shuffle<T>(this T[] array)
{
rng = new Random();
int n = array.Length;
while (n > 1)
{
int k = rng.Next(n);
n--;
T temp = array[n];
array[n] = array[k];
array[k] = temp;
}
}
}
}
string[] names = new string[] {
"Aaron Moline1",
"Aaron Moline2",
"Aaron Moline3",
"Aaron Moline4",
"Aaron Moline5",
"Aaron Moline6",
"Aaron Moline7",
"Aaron Moline8",
"Aaron Moline9",
};
names.Shuffle<string>();
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;
}
public static class EnumerableExtensions
{
static readonly RNGCryptoServiceProvider RngCryptoServiceProvider = new RNGCryptoServiceProvider();
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> enumerable)
{
var randomIntegerBuffer = new byte[4];
Func<int> rand = () =>
{
RngCryptoServiceProvider.GetBytes(randomIntegerBuffer);
return BitConverter.ToInt32(randomIntegerBuffer, 0);
};
return from item in enumerable
let rec = new {item, rnd = rand()}
orderby rec.rnd
select rec.item;
}
}
Enumerable.Range(0,1000).Shuffle().ToList()
Random random = new Random();
array.ToList().Sort((x, y) => random.Next(-1, 1)).ToArray();
class Program
{
static string[] words1 = new string[] { "brown", "jumped", "the", "fox", "quick" };
static void Main()
{
var result = Shuffle(words1);
foreach (var i in result)
{
Console.Write(i + " ");
}
Console.ReadKey();
}
static string[] Shuffle(string[] wordArray) {
Random random = new Random();
for (int i = wordArray.Length - 1; i > 0; i--)
{
int swapIndex = random.Next(i + 1);
string temp = wordArray[i];
wordArray[i] = wordArray[swapIndex];
wordArray[swapIndex] = temp;
}
return wordArray;
}
}
int[] numbers = {0,1,2,3,4,5,6,7,8,9};
List<int> numList = new List<int>();
numList.AddRange(numbers);
Console.WriteLine("Original Order");
for (int i = 0; i < numList.Count; i++)
{
Console.Write(String.Format("{0} ",numList[i]));
}
Random random = new Random();
Console.WriteLine("\n\nRandom Order");
for (int i = 0; i < numList.Capacity; i++)
{
int randomIndex = random.Next(numList.Count);
Console.Write(String.Format("{0} ", numList[randomIndex]));
numList.RemoveAt(randomIndex);
}
Console.ReadLine();