2017-01-01 55 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