2013-06-22 49 views
3

我有下面的類:我如何在C#中獲得隨機條目的隨機大小的列表了一個IEnumerable <>的

public class Question 
{ 
    public int QuestionId { get; set; } 
    public string Title { get; set; } 
} 

,並在一個變量,我有:

IEnumerable<Question> _questions = GetQuestions.Get(); 

如何我可以收集變量_questions中的問題集合,並隨機返回集合中出現1到4個隨機問題的列表?

+2

請參閱http://stackoverflow.com/questions/1287567,然後只需使用'.Take()'提供您想要的問題數量(只需使用Random.Next即可獲得1至4之間的隨機數) 。 –

回答

7

可以洗牌列表,然後再使用Take()

var result = _questions.OrderBy(x => Guid.NewGuid()) 
         .Take(new Random().Next(4) + 1); 
+2

將參數設爲'Take'是1-4之間的隨機整數,這將是一個完整的答案。 – Oded

+0

這將採取列表中的前四項...... – Tim

+0

@Tim - 第一個_random_四。 – Oded

3

您可以使用Reservoir Sampling,使單次通過未知大小的順序隨機選擇一組的N項

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; 
} 

你使用這樣的:

IEnumerable<Question> questions = ...; 
Random rng = new Random(); 
int questionCount = rng.Next(1, 5); // Get between 1 and 4 questions. 

List<Question> randomQuestions = RandomlyChooseItems(questions, questionCount, rng); 

這通常比將項目複製到數組中並執行Fisher-Yates shuffle效率更高,但如果列表的大小可以選擇非常大並且要選擇的項目數量相對較小,您只需要存儲所選項目而不是原始項目列表。