根据值从字典中挑选随机条目

时间:2016-11-16 13:47:22

标签: c# dictionary random

我有一张餐馆的字典和一种类似这样的餐馆:Dictionary<Restaurant, string>餐馆是我的班级,为了简单起见,我在餐馆用字符串。

假设我的列表中有25个条目,其中可以有3个,4个或5个相同类型的餐馆。现在我想缩小范围,以便为每种类型选择1个随机元素。

我找到了this页面,其中解释了如何从字典中选择随机值,但是如何根据类型分组选择随机条目?

如果我需要详细说明或者您是否需要其他信息,请告诉我们!

编辑:我的代码示例:

Dictionary<Restaurant, string> restaurants = new Dictionary<Restaurant, string>();

randomRestaurants.Add(restaurants.GroupBy(x => x.string).//Randomly pick an entry per grouping and add it to list//

List<Restaurant> randomRestaurants = new List<Restaurant>();

例如:可能的类型可以是ItalianFast foodSushi

我想就另一个令人困惑的问题道歉。在发布内容之前,我会更加关注。

3 个答案:

答案 0 :(得分:1)

第一个想法(对于此列表的任何用法)是将您的数据源命令为更合理的格式,即键值结构,其中键类型是标识餐馆子集的字符串(字符串),并且值是其中的餐馆列表。

您可以使用类似于以下内容的代码执行此操作:

var sensibleDict = sillyDict
    .GroupBy(kv => kv.Value)
    .ToDictionary(
        m => m.Key,
        m => m.Select(kv => kv.Key).ToList());

现在,我们可以简单地将结果随机化并在随机化后取第一个将其转换为Key =&gt;单值项目。

var randomDict = sillyDict
    .GroupBy(kv => kv.Value)
    .ToDictionary(
        m => m.Key,
        m => m.Select(kv => kv.Key)
            .OrderBy(k => Guid.NewGuid())
            .Take(1)
            .First());

这会得到Dictionary<string, Restaurant>,其中第一个字符串是食物类型(即意大利语,寿司),第二个字符串是随机Restaurant

注意:正如我在评论中所说,如果您的数据集变大,这不是订购列表的最有效方式。有关改组列表的更好方法,请查看at this answer - Randomise a List

答案 1 :(得分:0)

尝试这种方式:

var restaurants = new Dictionary<string, List<Restaurant>();

//when u want to add a restaurant do this way:
var restaurant = new Restaurant { Type = "Sushi" };
List<Restaurant> res;
if(restaurants.TryGet(restaurant.Type, out res){
 res.Add(restaurant);
}
else restaurants.Add(restaurant.Type, new List<Restaurant> { restaurant });

// get random from a type
List<Restaurant> res2;
var type = "Sushi";
if(restaurants.TryGet(type, out res2){
 return res2[rand.Next(res2.Count)]
}

答案 2 :(得分:0)

根据您提供的链接,您可以使用IGrouping代替Dictionary的扩展方法(顺便说一句。为什么要以这种方式使用Dictionary,不会&# 39;只是将属性RestaurantType添加到Restaurant类更简单吗?)

public static class Ext
{
    public static IEnumerable<TValue> RandomValues<TKey, TValue>(this IGrouping<TKey, TValue> grouping, int count)
    {
        Random rand = new Random();
        List<TValue> values = grouping.ToList();
        int size;
        while (count>0 && values.Count>0)
        {
            size = values.Count;
            var v = values[rand.Next(size)];
            values.Remove(v);
            count--;
            yield return v;
        }
    }
}

使用代码:

       // example data
       Dictionary<Restaurant, string> restaurants = new Dictionary<Restaurant, string>();
        restaurants.Add(new Restaurant("r1") ,"A");
        restaurants.Add(new Restaurant("r2") ,"B");
        restaurants.Add(new Restaurant("r3") ,"A");
        restaurants.Add(new Restaurant("r4") ,"B");
        restaurants.Add(new Restaurant("r5") ,"A");
        restaurants.Add(new Restaurant("r6") ,"B");
        restaurants.Add(new Restaurant("r7") ,"A");
        restaurants.Add(new Restaurant("r8") ,"B");

        // 3 Random restaurants from group "A"
        List<Restaurant> randomRestaurants = restaurants.GroupBy(a=>a.Value).FirstOrDefault(a=>a.Key=="A")
            .RandomValues(3).Select(x=>x.Key).ToList();
        randomRestaurants.Clear();

        // 1 random restaurant per group
         List<Restaurant> randomRestaurants2 = restaurants
             .GroupBy(a => a.Value)
             .Select(a => a.RandomValues(1).FirstOrDefault().Key)
             .ToList();

         // or, with SelectMany, 2 random restaurants per type:
              List<Restaurant> randomRestaurants3 = restaurants.GroupBy(a => a.Value)
             .SelectMany(a => a.RandomValues(2))
             .Select(d=>d.Key).ToList();