获取具有不同类型的固定长度的随机项

use*_*430 12 c# linq

我有一个List<Fruit>,

public class Fruit
{
    public string Name { get; set; }
    public string Type { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

并且上面的列表包含两种类型的30个Fruit对象: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" });
.....
Run Code Online (Sandbox Code Playgroud)

我如何获得10个随机水果的清单(来自30个水果的篮子),但应该有3个橙子和7个苹果?

Mar*_*und 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();
Run Code Online (Sandbox Code Playgroud)

同样适用于oranges,"Orange"而不是"Apple"和3而不是7.

它是如何工作的?

OrderBy按给定条件对可枚举进行排序.因为Guid.NewGuid()返回随机唯一标识符,结果是项目是随机排序的.当我们申请时Take( n ),它会采用n此随机顺序中的第一项.

请注意,Guid您可以创建一个实例Random并将其f => random.NextDouble()用作OrderBy表达式.这可能是一个更安全的解决方案,因为Guid.NewGuid()不能保证是随机的,只能是唯一的.

  • 请记住,`Guid.NewGuid()`不会"保证"生成guid的"随机性".请阅读[此](http://stackoverflow.com/a/3169165/1565525)答案的Eric Lippert的评论.然后我认为你可以使用[this](http://stackoverflow.com/a/1287572/1565525)答案中提供的方法. (10认同)
  • 虽然这不是一个计算机科学问题,但我会不惜一切代价避免使用"真正随机"一词 (4认同)

Par*_*udy 5

首先,将苹果和橙子分开,这样你就可以了

var apples = basket.Where(f => f.Type == "Apple");
var oranges = basket.Where(f => f.Type == "Orange");
Run Code Online (Sandbox Code Playgroud)

现在,为了在不重复两个列表的情况下随机数量的元素,您可以使用以下内容:

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

最后,结合你得到的两个列表.


pap*_*zzo 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;
    }
}
Run Code Online (Sandbox Code Playgroud)