我一直在玩/研究如何随机化字符串中字符的顺序。坦白说,我只是不明白该怎么做。我搜索了C#文档和一些网站。我发现了一种在字符串中随机化字符顺序的特殊方法,但我不明白它是如何工作的。我还读到Random类不是真正随机的,这可以解释为什么结果如此相似。
我正在使用的当前方法的功能是什么(特别是OrderBy()方法)。 有更好的方法吗?
当前代码
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();
这是我尝试随机化,但根本不起作用:
*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()));
}*
提前感谢您的任何帮助。我会在此期间继续研究。
答案 0 :(得分:5)
尽管您找到的代码很短,但它并没有对原始字符串进行良好分布的随机播放:随机数发生器可能会在生成随机播放的过程中为您提供相同的数字,从而增加相应字符的概率将保留与原始字符串相同的顺序。
此问题的一个解决方案是使用Fisher–Yates shuffle。它很容易实现(你需要远离common implementation errors)。
由于string
是不可变的,因此您需要对一组字符进行随机播放,然后从中生成string
。
答案 1 :(得分:1)
要添加Fisher-Yates shuffle的建议,这里是一个代码示例,只是忽略测试断言,只是尝试调试并确保它足够随机。
[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;
}
}
}
答案 2 :(得分:0)
另一个例子......
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();
}