[英]How can I pick a random string from a list and assign it to a variable C#
[英]How can I pick random objects out of a list with C#?
我有一個包含超過300個對象的IQueryable:
public class Detail
{
public int Id { get; set; }
public int CityId { get; set; }
public bool Chosen { get; set; }
}
IQueryable<Detail> details = ...
我怎么能反對這個隨機選擇50個對象? 我假設我需要使用.ToList()轉換它,但我不確定如何挑選隨機元素。
300不是很多,所以是的,使它成為一個列表:
IQueryable<Detail> details = ...
IList<Detail> detailList = details.ToList();
現在你可以選擇一個隨機項目:
var randomItem = detailList[rand.Next(detailList.Count)];
你可以重復50次。 然而,這將導致重復,並且消除它們的過程將變得混亂。
所以使用標准的shuffle算法 ,然后選擇前50個:
Shuffle(detailList);
var selection = detailList.Take(50);
如果您事先知道隨機選擇的項目總數,則可以在不先轉換為列表的情況下進行。
以下方法將為您完成:
/// <summary>Randomly selects items from a sequence.</summary>
/// <typeparam name="T">The type of the items in the sequence.</typeparam>
/// <param name="sequence">The sequence from which to randomly select items.</param>
/// <param name="count">The number of items to randomly select from the sequence.</param>
/// <param name="sequenceLength">The number of items in the sequence among which to randomly select.</param>
/// <param name="rng">The random number generator to use.</param>
/// <returns>A sequence of randomly selected items.</returns>
/// <remarks>This is an O(N) algorithm (N is the sequence length).</remarks>
public static IEnumerable<T> RandomlySelectedItems<T>(IEnumerable<T> sequence, int count, int sequenceLength, System.Random rng)
{
if (sequence == null)
{
throw new ArgumentNullException("sequence");
}
if (count < 0 || count > sequenceLength)
{
throw new ArgumentOutOfRangeException("count", count, "count must be between 0 and sequenceLength");
}
if (rng == null)
{
throw new ArgumentNullException("rng");
}
int available = sequenceLength;
int remaining = count;
var iterator = sequence.GetEnumerator();
for (int current = 0; current < sequenceLength; ++current)
{
iterator.MoveNext();
if (rng.NextDouble() < remaining/(double)available)
{
yield return iterator.Current;
--remaining;
}
--available;
}
}
(這里的關鍵是需要在開始時知道可供選擇的項目數量;這確實會減少實用程序。但是如果快速獲取計數並且緩沖所有項目會占用太多內存,這是一個有用的解決方案。)
這是另一種使用油藏采樣的方法
這種方法不需要知道可供選擇的項目總數,但它確實需要緩沖輸出。 當然,它還需要枚舉整個輸入集合。
因此,當您事先不知道可供選擇的項目數量(或者可供選擇的項目數量非常大)時,這實際上只是有用。
我建議只按照Henk的答案洗牌,而不是這樣做,但我為了感興趣而把它包括在這里:
// n is the number of items to randomly choose.
public static List<T> RandomlyChooseItems<T>(IEnumerable<T> items, int n, Random rng)
{
var result = new List<T>(n);
int index = 0;
foreach (var item in items)
{
if (index < n)
{
result.Add(item);
}
else
{
int r = rng.Next(0, index + 1);
if (r < n)
result[r] = item;
}
++index;
}
return result;
}
作為Henk答案的附錄,這里是他提到的Shuffle算法的規范實現。 在這里, _rng
是Random
一個實例:
/// <summary>Shuffles the specified array.</summary>
/// <typeparam name="T">The type of the array elements.</typeparam>
/// <param name="array">The array to shuffle.</param>
public void Shuffle<T>(IList<T> array)
{
for (int n = array.Count; n > 1;)
{
int k = _rng.Next(n);
--n;
T temp = array[n];
array[n] = array[k];
array[k] = temp;
}
}
Random rnd = new Random();
IQueryable<Detail> details = myList.OrderBy(x => rnd.Next()).Take(50);
IQueryable<Detail> details = myList.OrderBy(x => Guid.NewGuid()).ToList();
在這之后,直接走線:
var item1 = details[0];
這樣可以避免重復。
var l = new List<string>();
l.Add("A");
l.Add("B");
l.Add("C");
l.Add("D");
l.Add("E");
l.Add("F");
l.Add("G");
l.Add("H");
l.Add("I");
var random = new Random();
var nl = l.Select(i=> new {Value=i,Index = random.Next()});
var finalList = nl.OrderBy(i=>i.Index).Take(3);
foreach(var i in finalList)
{
Console.WriteLine(i.Value);
}
這最終為我工作,它確保沒有返回重復:
public List<T> GetRandomItems(List<T> items, int count = 3)
{
var length = items.Count();
var list = new List<T>();
var rnd = new Random();
var seed = 0;
while (list.Count() < count)
{
seed = rnd.Next(0, length);
if(!list.Contains(items[seed]))
list.Add(items[seed]);
}
return list;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.