如果这样,我可以从给定范围获得随机值:
int r = ran.Next(1, 4);
string v;
if (dict.TryGetValue(r, out v))
{
///...
}
如何从特定范围正确获取<int, string>
字典内容的随机值,例如仅从4到6和1和2,并避免查找3:
Dictionary<int, string> dict = new Dictionary<int, string>()
{
{ 1, "word1" },
{ 2, "word2" },
{ 3, "word3" },
{ 4, "word4" },
{ 5, "word5" },
{ 6, "word6" }
};
答案 0 :(得分:0)
使用排除值创建HashSet,然后
HashSet<int> excludedValues = ....
List<int> values = dict.Where(x=> excludedValues.Contains(x.Key) == false).Select(x=>x.Key).ToList();
int index = rand.Next(1, values.Count);
string value = dict[index];
这样您不仅可以排除值3.您可以在此集合中添加任何内容。如果你的集合很大,你应该使用比List更快的hashset。
答案 1 :(得分:0)
一般情况下,LINQ
中提供了一些功能,即IEnumerable.Skip和IEnumerable.Take
这些函数可用于获取任何IEnumerable
的切片。请注意,Dictionary<TKey, TValue>
也是IEnumerable<KeyValuePair<TKey, TValue>>
所以要访问第4和第10个元素之间的随机元素。
var rand = new Random();
dict.Skip(3).Take(6 /* 10 - 4 */).ElementAt(rand.Next(6 /* 10 - 4 */)
现在请记住,序列不一定按键或以任何可预测的方式排序或排序。您可能必须使用OrderBy
按您选择的顺序遍历字典。
如果您希望在字词更新之间多次执行这些操作,那么您只需访问dict.Keys.OrderBy().ToList()
,然后使用相同的List
或直接使用索引操作访问此Skip().Take().ElementAt()
。这样可以避免多次重新枚举同一个字典
答案 2 :(得分:0)
您可以收集所有可以采用的值,然后从中选择随机值:
private static Random s_Random = new Random();
...
var values = dict
.Where(pair => pair.Key >= 4 && pair.Key <= 6 || // conditions on key
pair.Key >= 1 && pair.Key <= 2)
.ToArray();
var result = values[s_Random.Next(values.Length)];
答案 3 :(得分:0)
使用此解决方案,您可以获得指定范围内的随机值,而无需首先迭代字典。
void Main()
{
Dictionary<int, string> dict = new Dictionary<int, string>()
{
{ 1, "word1" },
{ 2, "word2" },
{ 3, "word3" },
{ 4, "word4" },
{ 5, "word5" },
{ 6, "word6" }
};
var randomizer = new Random();
GetRandomValue(dict, randomizer, new Range(4, 6), new Range(1,2)).Dump();
}
public TValue GetRandomValue<TValue>(IDictionary<int, TValue> dic, Random randomizer, params Range[] ranges)
{
var range = ranges[randomizer.Next(0, ranges.Length)];
var key = randomizer.Next(range.From, range.To + 1);
return dic[key];
}
public class Range
{
public Range(int @from, int to)
{
From = @from;
To = to;
}
public int From {get;set;}
public int To {get;set;}
}
答案 4 :(得分:0)
根据具体需要,最简单的方法是指定可能的数字:
int[] a { 1, 2, 4, 5, 6 };
int r = a[ran.Next(a.Length)];
或
int r = ran.Next(1, 6);
if (r == 3) r = 6;
答案 5 :(得分:-1)
以下是使用扩展方法的解决方案:
public static class RandomExtensions
{
public static int NextWithinRange(this Random random, params Range[] ranges)
{
if (ranges.Length > 0)
{
Range range = ranges[random.Next(0, ranges.Length)];
return random.Next(range.MinValue, range.MaxValue + 1);
}
return random.Next();
}
public class Range
{
public int MinValue { get; set; }
public int MaxValue { get; set; }
public Range(int minValue, int maxValue)
{
MinValue = minValue;
MaxValue = maxValue;
}
}
}
用法:
int r = ran.NextWithinRange(new Range(1, 2), new Range(4, 6));
string v;
if (dict.TryGetValue(r, out v))
{
///...
}
这是使用LINQ的解决方案:
var rand = new Random();
// create a new dictionary, filtering out any unwanted keys within range(s)
Dictionary<int, string> filteredDict =
dict.Where(pair => (pair.Key >= 1 && pair.Key <= 2)
|| (pair.Key >= 4 && pair.Key <= 6))
.ToDictionary(pair => pair.Key, pair => pair.Value);
// get a random entry from the filtered dictionary
KeyValuePair<int, string> entry = filteredDict.ElementAt(rand.Next(0, filteredDict.Count));
// get random entry's value
string value = entry.Value;
编辑:感谢@Kyle在我的帖子中指出了潜在的ArgumentOutOfRange
例外。