2017-01-01 96 views
12

的固定長度的隨機項我有一個List<Fruit>獲取與不同類型

public class Fruit 
{ 
    public string Name { get; set; } 
    public string Type { get; set; } 
} 

和上面的列表包含兩種類型的30個水果對象:AppleOrange。 20個蘋果和10個桔子。

List<Fruit> fruits = new List<Fruit>(); 
fruits.Add(new Fruit(){ Name = "Red Delicious", Type = "Apple" }); 
fruits.Add(new Fruit(){ Name = "Granny Smith", Type = "Apple" }); 
fruits.Add(new Fruit(){ Name = "Sour Granny", Type = "Orange" }); 
fruits.Add(new Fruit(){ Name = "Delicious Yummy", Type = "Orange" }); 
..... 

我怎樣才能獲得的10種隨機水果的清單(從30個水果筐),但應該有3個橙子和蘋果7?

+2

爲什麼3個橙子7個蘋果具體? – Abion47

回答

12

您可以使用LINQ和GuidRandom進行隨機選擇:

var apples = fruits. 
    Where(f => f.Type == "Apple"). //choose only from apples 
    OrderBy(f => Guid.NewGuid()). //order randomly 
    Take(7). //take 7 apples 
    ToList(); 

同樣爲oranges,只是"Orange"代替"Apple"並用3而不是7.

如何這行得通?

OrderBy按給定條件排序枚舉。因爲Guid.NewGuid()返回一個隨機的唯一標識符,結果是這些項目是隨機排列的。當我們然後申請Take(n),它將採取這個隨機順序n第一項。

注意,與其Guid您可以創建Random一個實例,並使用f => random.NextDouble()OrderBy表達。這可能是更安全的解決方案,因爲Guid.NewGuid()不保證是隨機的,只能是唯一的

+4

即使它不是一個計算機科學問題,我會不惜一切代價避免術語「真正隨機」 – haim770

+1

該代碼是否與以下行一起工作:'OrderBy(f => a => Guid.NewGuid())' –

+1

@Kevin Wallis - 謝謝你的觀察,我一定以爲是「兩次」:-D –

5

首先,蘋果和橘子之間分開的,所以你必須

var apples = basket.Where(f => f.Type == "Apple"); 
var oranges = basket.Where(f => f.Type == "Orange"); 

現在爲了元素的隨機數,而不從兩份名單重複,你可以使用這樣的事情:

var random = new Random(); 
var numOfElements = 7; // Replace this with the number you want 
apples.OrderBy(x => random.Next()).Take(numOfElements).ToList(); 

最後,結合你得到的兩個列表。

5

您可以隨機播放一次,然後剝離蘋果和桔子
這將是一個多一點效率比隨機對每個水果,但短名單上不會有太大的區別

public static void TestFruit() 
{ 
    List<Fruit> fruits = new List<Fruit>(); 
    fruits.Add(new Fruit("01", "orange")); fruits.Add(new Fruit("02", "orange")); 
    fruits.Add(new Fruit("03", "orange")); fruits.Add(new Fruit("04", "orange")); 
    fruits.Add(new Fruit("05", "orange")); fruits.Add(new Fruit("06", "orange")); 
    fruits.Add(new Fruit("07", "orange")); fruits.Add(new Fruit("08", "orange")); 
    fruits.Add(new Fruit("09", "orange")); fruits.Add(new Fruit("10", "orange")); 
    fruits.Add(new Fruit("01", "apple")); fruits.Add(new Fruit("02", "apple")); 
    fruits.Add(new Fruit("03", "apple")); fruits.Add(new Fruit("04", "apple")); 
    fruits.Add(new Fruit("05", "apple")); fruits.Add(new Fruit("06", "apple")); 
    fruits.Add(new Fruit("07", "apple")); fruits.Add(new Fruit("08", "apple")); 
    fruits.Add(new Fruit("09", "apple")); fruits.Add(new Fruit("10", "apple")); 
    fruits.Add(new Fruit("11", "apple")); fruits.Add(new Fruit("12", "apple")); 
    fruits.Add(new Fruit("13", "apple")); fruits.Add(new Fruit("14", "apple")); 
    fruits.Add(new Fruit("15", "apple")); fruits.Add(new Fruit("16", "apple")); 
    fruits.Add(new Fruit("17", "apple")); fruits.Add(new Fruit("18", "apple")); 
    fruits.Add(new Fruit("19", "apple")); fruits.Add(new Fruit("20", "apple")); 
    Shuffle<Fruit>(fruits); 
    List<Fruit> randomFruits = fruits.Where(x => x.Type == "apple").Take(7).ToList(); 
    randomFruits.AddRange(fruits.Where(x => x.Type == "orange").Take(3)); 
    foreach (Fruit f in randomFruits) 
    { 
     Debug.WriteLine("Name {0} Type {1}", f.Name, f.Type); 
    } 
    Debug.WriteLine(""); 
} 
public static void Shuffle<T>(List<T> list) 
{ // FisherYates 
    for (int i = list.Count - 1; i >= 1; i--) 
    { 
     int j = rand.Next(i + 1); 
     if (j != i) 
     { // exchange values 
      T curVal = list[i]; 
      list[i] = list[j]; 
      list[j] = curVal; 
     } 
    } 
} 
public class Fruit 
{ 
    public string Name { get; set; } 
    public string Type { get; set; } 
    public Fruit(string name, string type) 
    { 
     Name = name; 
     Type = type; 
    } 
} 
+0

愚蠢的狗仔隊,你不需要去掉蘋果,你可以把它們留在皮膚上! –

+0

@ScottChamberlain脫皮是常見的撲克術語 – Paparazzi