c#中的随机名称生成器
本文关键字:随机 | 更新日期: 2023-09-27 17:57:47
我有一个女性和男性名字的列表,然后是数组中的姓氏列表。
我试图做的是使用随机生成器获取这些数组中的名称,并根据我的调用输出随机的名字和姓氏。
完成后,我将在其他类中引用该方法,而不必每次都写出来。
这是我迄今为止的代码:
private void RandName()
{
string[] maleNames = new string[1000] { "aaron", "abdul", "abe", "abel", "abraham", "adam", "adan", "adolfo", "adolph", "adrian"};
string[] femaleNames = new string[1000] { "abby", "abigail", "adele", "adrian"};
string[] lastNames = new string[1000] { "abbott", "acosta", "adams", "adkins", "aguilar"};
Random rand = new Random(DateTime.Now.Second);
if (rand.Next(1, 2) == 1)
{
FirstName = maleNames[rand.Next(0, maleNames.Length - 1)];
}
else
{
FirstName = femaleNames[rand.Next(0, femaleNames.Length - 1)];
}
}
我的问题是:如何使用我创建的名称数组创建随机名称生成器?
public static string GenerateName(int len)
{
Random r = new Random();
string[] consonants = { "b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "l", "n", "p", "q", "r", "s", "sh", "zh", "t", "v", "w", "x" };
string[] vowels = { "a", "e", "i", "o", "u", "ae", "y" };
string Name = "";
Name += consonants[r.Next(consonants.Length)].ToUpper();
Name += vowels[r.Next(vowels.Length)];
int b = 2; //b tells how many times a new letter has been added. It's 2 right now because the first two letters are already in the name.
while (b < len)
{
Name += consonants[r.Next(consonants.Length)];
b++;
Name += vowels[r.Next(vowels.Length)];
b++;
}
return Name;
}
我想你的随机生成器每次的结果都是一样的。。
如果这是您的问题,则不应该每次都创建局部变量rand
。改为创建字段。
Smth样:
private static Random rand = new Random(DateTime.Now.Second);
private void RandName()
{
...
}
好吧,在不知道您面临的问题的情况下,这有点像暗箭伤人,但我认为您的问题是,您已经将数组大小声明为1000
,但每个数组中只输入了大约10个值。因此,您的数组只有1%的满,因此您将获得大部分空名称。
尝试以下操作:
// Note I have not specified the array size.
string[] maleNames = {"aaron", "abdul", "abe", "abel", "abraham", "adam", "adan", "adolfo", "adolph", "adrian"};
string[] femaleNames = {"abby", "abigail", "adele", "adrian"};
string[] lastNames = {"abbott", "acosta", "adams", "adkins", "aguilar"};
由于随机实例是在RandName
中创建的,因此当方法被快速调用时(例如在循环中),您将创建相同的名称。您应该使用一个字段或将random作为参数传递给该方法。
除此之外,您将永远无法访问此处的else
块
if (rand.Next(1, 2) == 1)
因为CCD_ 5的第二参数是排他上界并且它总是生成1。所以你可能想要这个:
if (rand.Next(0, 2) == 1)
像这样格式化字符串…
string[] maleNames = new string[] { "aaron", "abdul", "abe", "abel", "abraham", "adam", "adan", "adolfo", "adolph", "adrian"};
string[] femaleNames = new string[] { "abby", "abigail", "adele", "adrian"};
string[] lastNames = new string[] { "abbott", "acosta", "adams", "adkins", "aguilar"};
或者对我来说,更简单的方法是使用列表。我使用它们来迭代文件。主要区别在于,您必须使用List.add()一次添加一个条目,并且它使用List.Count而不是Array.Length.List。List还允许您修改条目,而无需调整数组的大小。在你的情况下,你试图创建的列表看起来像这个
List<string> maleNames = new List<string>();
List<string> femaleNames = new List<string>();
List<string> lastNames = new List<string>();
然后使用System.IO打开单独的文件,并读取三个列表中的每一行。我就是这么做的。
public string GenerateToken(Byte length) {
var bytes = new byte[length];
var rnd = new Random();
rnd.NextBytes(bytes);
return Convert.ToBase64String(bytes).Replace("=", "").Replace("+", "").Replace("/", "");
}
是一个非常简单的生成器。。
虽然我在2013年的第一个答案是一个已经过时的项目的仅链接答案,但我在测试中使用了以下代码:
namespace MockHelpers
{
public static class NameGenerator
{
private static readonly Random _Random = new Random();
private static readonly Lazy<string[]> _MaleNames = new Lazy<string[]>(() => Resources.MaleNames.Split((char[])null, StringSplitOptions.RemoveEmptyEntries));
private static readonly Lazy<string[]> _FemaleNames = new Lazy<string[]>(() => Resources.FemaleNames.Split((char[])null, StringSplitOptions.RemoveEmptyEntries));
private static readonly Lazy<string[]> _FamilyNames = new Lazy<string[]>(() => Resources.FamilyNames.Split((char[])null, StringSplitOptions.RemoveEmptyEntries));
public static IEnumerable<string> GetMaleNames()
{
return _MaleNames.Value.CreateEndlessRandomSequence(_Random);
}
public static IEnumerable<string> GetFemaleNames()
{
return _FemaleNames.Value.CreateEndlessRandomSequence(_Random);
}
public static IEnumerable<string> GetFamilyNames()
{
return _FamilyNames.Value.CreateEndlessRandomSequence(_Random);
}
public static IEnumerable<(string firstName, string lastName, Gender gender)> GetNames()
{
return new[] {
GetMaleNames().Select(Name => (Name, Gender.Male)),
GetFemaleNames().Select(Name => (Name, Gender.Female))
}
.Interweave()
.Zip(GetFamilyNames(), (person, lastName) => (person.Name, lastName, person.Item2));
}
}
public enum Gender
{
Unknown,
Female,
Male,
}
public static class EnumerableExtensions
{
public static IEnumerable<T> CreateEndlessRandomSequence<T>(this IReadOnlyList<T> source, Random rng)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
if (rng == null)
{
throw new ArgumentNullException(nameof(rng));
}
return CreateEndlessRandomSequenceIterator(source, rng);
}
public static IEnumerable<T> Interweave<T>(this IEnumerable<IEnumerable<T>> sources)
{
if (sources == null)
{
throw new ArgumentNullException(nameof(sources));
}
var enumerators = sources.Select(source => source.GetEnumerator()).ToList();
return InterweaveIterator(enumerators);
}
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
if (rng == null)
{
throw new ArgumentNullException(nameof(rng));
}
var elements = source.ToArray();
return ShuffleIterator(elements, rng);
}
private static IEnumerable<T> CreateEndlessRandomSequenceIterator<T>(IReadOnlyList<T> source, Random rng)
{
while (true)
{
var shuffled = source.Shuffle(rng);
foreach (var item in shuffled)
{
yield return item;
}
}
}
private static IEnumerable<T> InterweaveIterator<T>(List<IEnumerator<T>> enumerators)
{
try
{
while (true)
{
enumerators.RemoveAll(e =>
{
if (e.MoveNext())
return false;
e.Dispose();
return true;
});
if (enumerators.Count == 0)
yield break;
foreach (var e in enumerators)
yield return e.Current;
}
}
finally
{
if (enumerators != null)
foreach (var e in enumerators)
e.Dispose();
}
}
private static IEnumerable<T> ShuffleIterator<T>(T[] elements, Random rng)
{
for (int i = elements.Length - 1; i >= 0; i--)
{
// Swap element "i" with a random earlier element it (or itself)
// ... except we don't really need to swap it fully, as we can
// return it immediately, and afterwards it's irrelevant.
int swapIndex = rng.Next(i + 1);
yield return elements[swapIndex];
elements[swapIndex] = elements[i];
}
}
}
}
要使用它,您可以简单地调用:
foreach (var item in NameGenerator.GetNames().Take(1000))
{
Console.WriteLine($"{item.gender} {item.firstName} {item.lastName}");
}
此外,为了使此代码完全工作,您必须创建资源文件,其中包含所需的sur和给定名称列表。这些必须是简单的文本文件,每一个单独的名称都在一行上,比如:
Michael
Christian
Peter