找到这个 Post在 List<T>
中洗牌时有很好的解决方案.
但在我的例子中,我有一个类 Person
定义如下:
class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Position { get; set; }
}
这是我的实现和用法:
List<Person> workers = new List<Person>()
{
new Person { Id = 1, Name = "Emp 1", Position = "Cashier"},
new Person { Id = 2, Name = "Emp 2", Position = "Sales Clerk"},
new Person { Id = 3, Name = "Emp 3", Position = "Cashier"},
new Person { Id = 4, Name = "Emp 4", Position = "Sales Clerk"},
new Person { Id = 5, Name = "Emp 5", Position = "Sales Clerk"},
new Person { Id = 6, Name = "Emp 6", Position = "Cashier"},
new Person { Id = 7, Name = "Emp 7", Position = "Sales Clerk"}
};
现在我想洗牌所有记录并获得 1 名销售员。这是我的代码并且正在运行:
var worker = workers.OrderBy(x => Guid.NewGuid()).Where(x => x.Position == "Sales Clerk").First();
// This can yield 1 of this random result (Emp 2, Emp 4, Emp 5 and Emp 7).
Console.WriteLine(worker.Name);
但是根据给定的Post GUID 不利于随机化记录。最糟糕的是我不能使用 Shuffle()
并调用Where
和 First()
扩展以获得所需的结果。
我如何使用 Shuffle()
做到这一点?扩展名?
如果问题是如何获取它以便您可以将 Shuffle() 与其余的 Linq 运算符链接起来,答案是修改 Shuffle 方法以返回对已洗牌列表的引用:
public static IEnumerable<T> Shuffle<T>(this IList<T> list)
{
RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider();
int n = list.Count;
while (n > 1)
{
byte[] box = new byte[1];
do provider.GetBytes(box);
while (!(box[0] < n * (Byte.MaxValue / n)));
int k = (box[0] % n);
n--;
T value = list[k];
list[k] = list[n];
list[n] = value;
}
return list;
}
您的代码将变为:
var worker = workers.Shuffle().Where(x => x.Position == "Sales Clerk").First();
我是一名优秀的程序员,十分优秀!