【发布时间】:2018-10-18 23:37:36
【问题描述】:
我最近开始使用 C# 并正在开发一个程序,我需要从字典中删除 n 随机值。我从this previous q&a 中提取了一些代码并添加了DropRandom 以删除n 值,但是当我运行DropRandom(比如keepN = 10)时,字典不会直接下降到10 个值。
例如,从最初的总计数 100 到期望的最终计数 10,计数可能会下降到 20。我可以在结果字典上运行 DropRandom,然后它会下降到 12,最后是第三次(或第四次或第五次......)迭代将减少到 10 次。
所以我的问题是,我该怎么做才能让DropRandom 立即下降到所需的计数?
第一部分只是设置随机密钥(改编自上述问答):
public static IEnumerable<TKey> RandomKeys<TKey, TValue>(IDictionary<TKey,TValue> dictionary)
{
Random random = new Random();
List<TKey> keys = Enumerable.ToList(dictionary.Keys);
int size = dictionary.Count();
while (true) //returns random order of keys from dictionary using infinite loop
{
yield return keys[random.Next(size)];
}
}
第二部分删除除n 之外的所有值:
public static void DropRandom<TKey, TValue>(int keepN, ref Dictionary<TKey, TValue> dictionary)
{
if(dictionary.Count() < keepN)
{
throw new Exception("Trying to keep more items than in dictionary");
}
Console.WriteLine("old dict size = " + dictionary.Count());
Dictionary<TKey, TValue> tempDict = new Dictionary<TKey, TValue>();
//inelegant way to get extra values...
IEnumerable<TKey> randK = RandomKeys(dictionary).Take(keepN * 2);
while (tempDict.Count() < keepN)
{
foreach(TKey key in randK)
{
if (!tempDict.ContainsKey(key))
{
tempDict.Add(key, dictionary[key]);
Console.WriteLine("key = " + key.ToString());
}
}
}
dictionary = null;
dictionary = tempDict;
Console.WriteLine("New dict size = " + dictionary.Count());
}
【问题讨论】:
-
你是内在的
if还需要对keepN进行计数检查,否则你添加来自randK的所有键。我建议使用Fisher-Yates shuffle 来获得随机顺序的键,而不是希望取两倍的键不会导致太多重复。 -
KeepN 会比 N 小很多吗?
-
@juharr,谢谢你的建议,我会研究一下洗牌。另外,keepN 总是比 N 小很多。
标签: c#