在c#中随机化泛型列表顺序的最佳方法是什么?我在一个列表中有一个有限的75个数字集,我想随机分配一个顺序,以便为彩票类型的应用程序绘制它们。
当前回答
I'm bit surprised by all the clunky versions of this simple algorithm here. Fisher-Yates (or Knuth shuffle) is bit tricky but very compact. Why is it tricky? Because your need to pay attention to whether your random number generator r(a,b) returns value where b is inclusive or exclusive. I've also edited Wikipedia description so people don't blindly follow pseudocode there and create hard to detect bugs. For .Net, Random.Next(a,b) returns number exclusive of b so without further ado, here's how it can be implemented in C#/.Net:
public static void Shuffle<T>(this IList<T> list, Random rnd)
{
for(var i=list.Count; i > 0; i--)
list.Swap(0, rnd.Next(0, i));
}
public static void Swap<T>(this IList<T> list, int i, int j)
{
var temp = list[i];
list[i] = list[j];
list[j] = temp;
}
试试这段代码。
其他回答
public Deck(IEnumerable<Card> initialCards)
{
cards = new List<Card>(initialCards);
public void Shuffle()
}
{
List<Card> NewCards = new List<Card>();
while (cards.Count > 0)
{
int CardToMove = random.Next(cards.Count);
NewCards.Add(cards[CardToMove]);
cards.RemoveAt(CardToMove);
}
cards = NewCards;
}
public IEnumerable<string> GetCardNames()
{
string[] CardNames = new string[cards.Count];
for (int i = 0; i < cards.Count; i++)
CardNames[i] = cards[i].Name;
return CardNames;
}
Deck deck1;
Deck deck2;
Random random = new Random();
public Form1()
{
InitializeComponent();
ResetDeck(1);
ResetDeck(2);
RedrawDeck(1);
RedrawDeck(2);
}
private void ResetDeck(int deckNumber)
{
if (deckNumber == 1)
{
int numberOfCards = random.Next(1, 11);
deck1 = new Deck(new Card[] { });
for (int i = 0; i < numberOfCards; i++)
deck1.Add(new Card((Suits)random.Next(4),(Values)random.Next(1, 14)));
deck1.Sort();
}
else
deck2 = new Deck();
}
private void reset1_Click(object sender, EventArgs e) {
ResetDeck(1);
RedrawDeck(1);
}
private void shuffle1_Click(object sender, EventArgs e)
{
deck1.Shuffle();
RedrawDeck(1);
}
private void moveToDeck1_Click(object sender, EventArgs e)
{
if (listBox2.SelectedIndex >= 0)
if (deck2.Count > 0) {
deck1.Add(deck2.Deal(listBox2.SelectedIndex));
}
RedrawDeck(1);
RedrawDeck(2);
}
我们可以为List使用扩展方法,并使用线程安全的随机生成器组合。我在NuGet上打包了一个改进的版本,并在GitHub上提供源代码。NuGet版本包含可选的密码强随机。
Pre -。NET 6.0版本:
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Shuffle<T>(this IList<T> list)
{
if (list == null) throw new ArgumentNullException(nameof(list));
int n = list.Count;
while (n > 1)
{
int k = ThreadSafeRandom.Instance.Next(n--);
(list[n], list[k]) = (list[k], list[n]);
}
}
internal class ThreadSafeRandom
{
public static Random Instance => _local.Value;
private static readonly Random _global = new Random();
private static readonly ThreadLocal<Random> _local = new ThreadLocal<Random>(() =>
{
int seed;
lock (_global)
{
seed = _global.Next();
}
return new Random(seed);
});
}
在。net 6.0或更高版本上:
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Shuffle<T>(this IList<T> list)
{
ArgumentNullException.ThrowIfNull(list);
int n = list.Count;
while (n > 1)
{
int k = Random.Shared.Next(n--);
(list[n], list[k]) = (list[k], list[n]);
}
}
通过NuGet安装库以获得更多功能。
想法是获得匿名对象的项目和随机顺序,然后按此顺序重新排序项目,并返回值:
var result = items.Select(x => new { value = x, order = rnd.Next() })
.OrderBy(x => x.order).Select(x => x.value).ToList()
private List<GameObject> ShuffleList(List<GameObject> ActualList) {
List<GameObject> newList = ActualList;
List<GameObject> outList = new List<GameObject>();
int count = newList.Count;
while (newList.Count > 0) {
int rando = Random.Range(0, newList.Count);
outList.Add(newList[rando]);
newList.RemoveAt(rando);
}
return (outList);
}
用法:
List<GameObject> GetShuffle = ShuffleList(ActualList);
IEnumerable扩展方法:
public static IEnumerable<T> Randomize<T>(this IEnumerable<T> source)
{
Random rnd = new Random();
return source.OrderBy<T, int>((item) => rnd.Next());
}