C# 从列表中随机抽取30个元素
我有一个字符串列表,其中包含大量带有文本的hashtag。 例如,csharp、java等。 每个hashtag都是列表中自己的字符串。现在,我想随机始终console.writeline列表中的30项 名单C# 从列表中随机抽取30个元素,c#,list,random,C#,List,Random,我有一个字符串列表,其中包含大量带有文本的hashtag。 例如,csharp、java等。 每个hashtag都是列表中自己的字符串。现在,我想随机始终console.writeline列表中的30项 名单 理想情况下,我不想在random 30中使用相同的标签。调用random 30次。下一步 你应该试试这个: var rnd = new Random(); foreach (var x in Hashtags.OrderBy(x => rnd.Next()).Take(30))
理想情况下,我不想在random 30中使用相同的标签。调用random 30次。下一步 你应该试试这个:
var rnd = new Random();
foreach (var x in Hashtags.OrderBy(x => rnd.Next()).Take(30))
{
Console.WriteLine(x);
}
这具有O(n^2)
复杂性,但易于阅读
如果您想提高效率,请尝试Fisher-Yates Shuffle,它是O(n)
,但可读性较差:
var take = 30;
var rnd = new Random();
for (var i = 0; i < (Hashtags.Count < take ? Hashtags.Count : take); i++)
{
var j = rnd.Next(Hashtags.Count);
(Hashtags[i], Hashtags[j]) = (Hashtags[j], Hashtags[i]);
}
foreach (var x in Hashtags.Take(take))
{
Console.WriteLine(x);
}
我自己做的,有点冗长,但希望更容易理解
var random = new Random();
var uniques = Hashtags;
for (var i = 0; i < 30; i++) {
var index = random.Next(0, uniques.Count());
Console.WriteLine(uniques[index]);
uniques.RemoveAt(index);
}
var random=new random();
var uniques=Hashtags;
对于(var i=0;i<30;i++){
var index=random.Next(0,uniques.Count());
Console.WriteLine(uniques[索引]);
唯一删除(索引);
}
这应该可以。它是高效的,因为它只洗牌所需数量的项目,而不是整个集合。将要从数组中提取的元素数作为参数传递(elementCount
)
private static Random Random generator=new Random();
静态void Main()
{
var hashtags=newlist(){“c#”,“javascript”,“ef”,“asp.net”};
var result=GetRandomItems(hashtags,2);
foreach(结果中的var项目)
{
控制台写入线(项目);
}
}
私有静态IEnumerable GetRandomItems(IEnumerable集合,int elementCount)
{
var collectionCount=collection.Count();
如果(elementCount>collectionCount)
{
elementCount=collectionCount;
}
var collectionCopy=collection.ToList();
var randomIndex=randomGenerator.Next(0,collectionCopy.Count);
对于(var index=0;index
到目前为止,您尝试了什么?什么不起作用?所有的30个字符串都以“#”开头?你在哪里尝试解决这个问题?这不是家庭作业编写服务。@MICHAMORF-Guid.NewGuid()
只保证是唯一的,而不是随机的。对于随机性,您应该始终使用RNG,而不要使用Guid
。@miscamorf不要在注释中发布尝试。用这些更新问题。唯一的缺点是你需要订购整个集合来挑选30个项目。@Magnus-没错,但是即使有一个包含1000个元素的列表,在我的计算机上排序也只需要不到半秒钟的时间。从好的方面来说,它保证会完成,并且它将使用一个比请求的数量更小的源列表。@Enigmativity仍然,这是一个非常短但效率非常低的解决方案。您不仅要对整个集合进行排序,这显然是一个问题,而且,更重要的是,您根本不需要对其进行排序,您只需要对给定数量的项进行无序排列。对不起,这不应该是一个被接受的答案。@zhulien-不,你是对的。我没有检查你的。你说得对。你的效率更高。@zhulien-我已经更新了我的。我觉得我现在的状态很好。这没有任何逻辑停止两次获取相同的hashtag,因为是随机的。next
代码可以多次返回相同的值。@Mishamorf-如果您试图避免重复,这不起作用。@Enigmativity我只是在写出字符串后将其从字符串列表中删除。然后它会:)@miscamorf-这样调整数组的大小效率很低。抱歉-您在我最后一次编辑之前发布了这篇文章。显然,您必须在顶部添加一些using语句,但我认为IDE至少会为您提供这些语句。即使您进行了最后的编辑,它仍然无法编译。对不起,我以为我发布了最后的编辑,但首先关闭了选项卡:)此外,没有方法DateTime.UtcNow.tounixtimesconds()
-它应该是DateTimeOffset.UtcNow.ToUnixTimeSeconds()
。现在,即使您尝试调用new Random(DateTimeOffset.UtcNow.ToUnixTimeSeconds())
,这也是一个语法错误。即使它确实有效,那么调用它也比仅仅调用new Random()
(内部使用Environment.TickCount
)糟糕一千倍。对于多个执行,应该使用同一个Random
实例,而不是试图创建一个新的或更糟的,使用秒作为种子。使用秒意味着在整整一秒钟内会产生相同的数字序列。很好。与其制作列表的副本,不如将列表(collection.Count())
(用于表示索引)混洗更有效。最好只混洗所需数量的项目。(仅供参考,关于.Select
的注释是您根本不需要它;collection.ToList()
将返回集合的副本
var rnd = new Random();
foreach (var x in Hashtags.OrderBy(x => rnd.Next()).Take(30))
{
Console.WriteLine(x);
}
var take = 30;
var rnd = new Random();
for (var i = 0; i < (Hashtags.Count < take ? Hashtags.Count : take); i++)
{
var j = rnd.Next(Hashtags.Count);
(Hashtags[i], Hashtags[j]) = (Hashtags[j], Hashtags[i]);
}
foreach (var x in Hashtags.Take(take))
{
Console.WriteLine(x);
}
[ThreadStatic]
private static Random rnd = new Random();
var random = new Random();
var uniques = Hashtags;
for (var i = 0; i < 30; i++) {
var index = random.Next(0, uniques.Count());
Console.WriteLine(uniques[index]);
uniques.RemoveAt(index);
}
private static Random randomGenerator = new Random();
static void Main()
{
var hashtags = new List<string>() { "c#", "javascript", "ef", "asp.net" };
var result = GetRandomItems<string>(hashtags, 2);
foreach (var item in result)
{
Console.WriteLine(item);
}
}
private static IEnumerable<T> GetRandomItems<T>(IEnumerable<T> collection, int elementCount)
{
var collectionCount = collection.Count();
if (elementCount > collectionCount)
{
elementCount = collectionCount;
}
var collectionCopy = collection.ToList();
var randomIndex = randomGenerator.Next(0, collectionCopy.Count);
for (var index = 0; index < elementCount; index++)
{
var tempElement = collectionCopy[index];
collectionCopy[index] = collectionCopy[randomIndex];
collectionCopy[randomIndex] = tempElement;
randomIndex = randomGenerator.Next(index + 1, collectionCopy.Count);
}
return collectionCopy.Take(elementCount);
}