C# 从哈希集中获取随机元素?
我使用下面的代码将我的文本文件加载到hashsetC# 从哈希集中获取随机元素?,c#,hashset,C#,Hashset,我使用下面的代码将我的文本文件加载到hashset HashSet<string> hashs = new HashSet<string>(File.ReadLines("textFile.txt")); HashSet hash=newhashset(File.ReadLines(“textFile.txt”); 我想知道是否有任何简单的方法可以从中获得一条随机线 假设textFile.txt包含10行,我想随机抽取其中一行。您可以生成一个介于0和集合大小之间的随机
HashSet<string> hashs = new HashSet<string>(File.ReadLines("textFile.txt"));
HashSet hash=newhashset(File.ReadLines(“textFile.txt”);
我想知道是否有任何简单的方法可以从中获得一条随机线
假设textFile.txt包含10行,我想随机抽取其中一行。您可以生成一个介于0和集合大小之间的随机数,然后在集合中迭代,直到找到索引与生成的数字相同的项。然后选择此项作为随机元素,或者为任何可枚举项选择更通用的解决方案
public static class RandomExtensions
{
private static readonly Random rnd = new Random();
private static readonly object sync = new object();
public static T RandomElement<T>(this IEnumerable<T> enumerable) {
if (enumerable == null)
throw new ArgumentNullException("enumerable");
var count = enumerable.Count();
var ndx = 0;
lock (sync)
ndx = rnd.Next(count); // returns non-negative number less than max
return enumerable.ElementAt(ndx);
}
}
公共静态类扩展
{
私有静态只读随机rnd=new Random();
私有静态只读对象同步=新对象();
公共静态T随机化元素(此IEnumerable可枚举){
if(可枚举==null)
抛出新ArgumentNullException(“可枚举”);
var count=enumerable.count();
var-ndx=0;
锁定(同步)
ndx=rnd.Next(count);//返回小于max的非负数
返回可枚举的.ElementAt(ndx);
}
}
无需每次都枚举整个数组,就可以得到一个类似于已接受答案的简单答案:
private static readonly Random random = new Random();
private static readonly HashSet<T> hashset = new HashSet<T>();
...
T element = hashset.ElementAt(random.Next(hashset.Count));
private static readonly Random=new Random();
私有静态只读HashSet HashSet=new HashSet();
...
T element=hashset.ElementAt(random.Next(hashset.Count));
自从.Net Framework 3.5以来,您可以使用Linq及其扩展方法。
不指定任何条件作为参数,此方法将返回
序列的第一个元素
你应该考虑使用<代码>枚举.FixStor()/代码>要求你的<代码> HASSETSE/COM>至少包含一个元素。 要检查此前提条件,您可以使用
HashSet.Count
或通过Linq with再次检查,而无需指定条件
HashSet<T> hashSet = new HashSet<T>();
...
if(hashSet.Any())
{
T randomElement = hashSet.First()
}
如果您计划绘制多个随机值,有效的方法是使用带有整数键的字典来存储信息
HashSet<string> hashs = new HashSet<string>();
Dictionary<int, string> lookup = new Dictionary<int, string>();
foreach (string line in File.ReadLines("textFile.txt")) {
if (hashs.Add(line)) {
lookup.Add(lookup.Count, line);
}
}
int randomInt = new Random().Next(lookup.Count);
string randomLine = lookup[randomInt];
HashSet hashs=new HashSet();
字典查找=新建字典();
foreach(File.ReadLines(“textFile.txt”)中的字符串行){
if(哈希添加(行)){
lookup.Add(lookup.Count,行);
}
}
int randomInt=new Random().Next(lookup.Count);
字符串randomLine=查找[randomInt];
(在本例中,您可以使用列表,但使用字典也可以删除单个元素而不影响顺序)。您尝试了什么?您是否尝试过使用System.Random类生成一个介于0和0之间的随机数,然后按索引引用该项?这些都是MSDN库中已经记录的任务。这个代码看起来怎么样?不知道怎么写:)1。谷歌“系统随机”。2.查看已经提供的文档和代码示例,这些示例可以在web上找到。3.学习,而不是使用复制/粘贴答案。(我想今天是我“急躁”的一天。)
ElementAt
将为空集合抛出异常。@lazyberezovsky如果ElementAt抛出,则RandomElement也应抛出相同的异常。在这种情况下应该有一个RandomElementDefault,ElementAT仍然枚举元素,直到它达到指定的索引,所以它不会更快。如果HashSet元素在多线程环境中更改,则可能返回InvalidOperationException(集合已修改;枚举操作可能无法执行)这可以通过在.ElementAt行上使用锁(对象)或.ToArray()来避免。hashset和store作为新变量将该锁(对象)用于rand Count和.ElementAt,但这可能不是内存效率,而是低效率的性能。并不是说我知道更好的方法,只是说。这将如何返回一个随机项?@derHugo HashSet是一个未排序的结构,所以第一个将是random@orion_tvv我猜每次你调用它时,它仍然会返回相同的元素。。。随机的!=如果您想通过多次调用获得不同的项,则不应使用HashSet,并且必须为转换为类似数组的结构而付费。但对于大多数用例来说,第一项是很好的折衷
T randomElement = hashSet.FirstOrDefault(default(T));
HashSet<string> hashs = new HashSet<string>();
Dictionary<int, string> lookup = new Dictionary<int, string>();
foreach (string line in File.ReadLines("textFile.txt")) {
if (hashs.Add(line)) {
lookup.Add(lookup.Count, line);
}
}
int randomInt = new Random().Next(lookup.Count);
string randomLine = lookup[randomInt];