问题描述
我有一个名称数组列表,其名称加1乘以1。随机数的范围是该数组列表中的人数。
例如: NameList => [詹姆斯,文斯,乔,约瑟夫,约翰]
我希望输出为
NameListNum => [詹姆斯3,文斯2,乔5,约瑟夫1,约翰4]
或
NameListNum => [詹姆斯2,文斯5,乔1,约瑟夫4,约翰3] \
foreach (var name in nameList)
{
counter++;
int randomNum = rand.Next(Decimal.ToInt32(numOfShooters))+1;
nameListNum.Add(name + " "+randomNum);
foreach (var item in nameListNum)
{
}
}
不知道我的方向是否正确,但是第二个foreach循环将是检查另一个nameListNum字符串并重新生成随机数并将其重写为名称的循环。
解决方法
鉴于它是very easy to find the code to Shuffle
a list随机生成的数字,因此代码就像
var namesList = new []{"James","Vince","Joe","Joseph","John"};
var numsList = Enumerable.Range(1,namesList.Length).ToList().Shuffle();
var namesNumsList = namesList.Select( (n,i) => $"{n} {numsList[i]}").ToList();
实时示例:https://dotnetfiddle.net/MzOwQa
如果您想随机化名称,请将其命名为List<string>
:
var namesList = new List<string>{"James","John"}.Shuffle();
唯一的其他更改是,您需要在下一行中用namesList.Count
代替namesList.Length
好的,让我们一步一步走。您有一个名称列表,并且想要为每个名称分配一个唯一的随机数。随机数必须在[1,number of names in the list]
幼稚的暴力方式是生成一个随机数,检查它是否已经滚动过,以及是否未将其分配给名称。依次对列表中的每个名称重复此过程,即可完成。
使用4或5个名称,它实际上运行得非常快,但很糟糕。当列表变得非常庞大时,甚至会变得浪费而且表现糟糕。为什么?好吧,您需要滚动很多次。
有更好的方法吗?是。想象一下您的问题是:编写一个在标准卡座中随机返回一张卡片的方法?你会用同样的方式做吗?还是您会以某种方式存储和订购卡座,对其进行洗牌,然后简单地一张一张地将卡片分发出去?
嗯,这里是一样的。您的标准套牌只是从1到射手总数的有序数字列表:1,2,3,....,numberOfShooters
。
现在,您将如何对其进行洗牌。好吧,天真的方法是创建一个列表,然后随机选择一个索引,选择存储在该列表中的数字,然后将其从列表中删除以避免再次滚动。那会起作用,但同样会浪费。为什么?因为重复删除列表中的项目可能很昂贵。记住列表只是标准数组的包装器;删除项目中间列表意味着必须将以下所有数字移到数组中的不上位置。
一种不产生所有这些问题的随机排列列表的简单方法是使用linq(有更好的方法,但是这足以满足您的情况):
var numbersToShuffle = Enumerable.Range(1,numberOfShooters);
var rnd = new Random();
numbersShuffled = numbersToShuffle.OrderBy(i => rnd.Next());
其余的应该很容易。