根据值从字典中随机选取条目
本文关键字:随机 选取 字典 | 更新日期: 2023-09-27 18:18:07
我有一个包含餐馆和餐馆类型的字典:Dictionary<Restaurant, string>
其中餐馆是我的类,为了简单起见,我使用字符串作为我的餐馆类型。
假设我的列表中有25个条目,其中可以有3个,4个或5个相同类型的餐厅。现在我想把范围缩小到每个类型随机选择1个元素。
我找到了这个页面,它解释了如何从字典中选择随机值,但是我如何去选择每个分组类型的随机条目?
让我知道如果我需要详细说明或如果你需要额外的信息!
编辑:我的代码示例: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>();
示例:可能的类型有:Italian
、Fast food
和Sushi
我很抱歉又问了一个令人困惑的问题。
第一个想法(对于此列表的任何用法)是将数据源排序为更合理的格式,即键值结构,其中键类型是标识餐馆子集(字符串)的东西,值是其中的餐馆列表。
您可以使用类似于以下的代码来完成此操作:
var sensibleDict = sillyDict
.GroupBy(kv => kv.Value)
.ToDictionary(
m => m.Key,
m => m.Select(kv => kv.Key).ToList());
现在,我们可以简单地随机化结果,并将随机化后的第一个结果转换为Key => Single Value项。
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
。
注意:正如我在评论中所说的,如果你的数据集很大,这不是排序列表的最有效方法。要了解更好的打乱列表的方法,请看下面的答案——随机化列表。
试试:
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)]
}
根据您提供的链接,您可以使用使用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();