基于值从字典中随机选择条目

3
我有一个餐厅的字典,格式如下:Dictionary<Restaurant, string>其中,Restaurant是我的类名,为简单起见,我使用字符串表示我的餐厅类型。
假设我有25个记录,其中可以分为3、4或5组具有相同类型的餐厅。现在我想从中选择每种类型的一个随机元素。
我已经找到了这个页面,它解释了如何从字典中选择随机值,但我该如何选择每个类型的一个随机条目?
如果需要更多说明或其他信息,请告诉我!
编辑:我的代码示例:
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>();

例如:可能的类型可以是意大利菜快餐寿司 我想为提出另一个令人困惑的问题道歉。在发布之前,我会更加注意。

1
请提供一个 [mcve],展示您当前的代码是什么样子。 - dymanoid
3
你的字典反了,应该从餐厅类型开始列出“餐厅”清单。 - user47589
@RudiVisser,请阅读我的问题,针对Amy,我如何基于我的字典来实现这个?不幸的是,我无法更改获取此数据的方式。 - user4189129
1
为了根据您的字典完成它,首先将其转换为Dictionary<string,List<Restaurant>>,以便您可以使用它。 - user47589
1
你可以通过这样做使它更有意义:var sensibleDict = sillyDict.GroupBy(kv => kv.Value).ToDictionary(m => m.Key, m => m.Select(kv => kv.Key).ToList()); 然后,你可以简单地随机化列表(使用诸如按Guid排序的方法)。我会写一个快速答案(请注意,这可能不是最有效的方法)。 - Rudi Visser
显示剩余7条评论
3个回答

1

首要想法(适用于此列表的任何使用)是将数据源排序为更合理的格式,即键值结构,其中键类型是标识餐厅子集的内容(字符串),而值是其中包含的餐厅列表。

您可以使用类似以下代码的代码来实现此目的:

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

现在,我们可以简单地随机化结果,并在随机化后取第一个来将其转换为键=>单值项。
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
注意:正如我在评论中所说,如果数据集变得很大,这不是对列表进行排序的最有效方式。有关更好的方法来洗牌列表,请查看此答案- 随机化列表

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)]
}

0
根据您提供的链接,您可以使用一个扩展方法,它接受 IGrouping 而不是 Dictionary(顺便问一下,为什么要以这种方式使用 Dictionary?将 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();

鲁迪已经帮了我很多,但是为了详细回答你的第一个问题,一家餐厅可以有多种类型。这与我的问题无关,因为我只想要每种类型中的一个随机餐厅。这就是我在示例中只使用字符串的原因。 - user4189129

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接