【问题标题】:Pick Random String From Array从数组中选择随机字符串
【发布时间】:2011-07-14 14:49:58
【问题描述】:

如何从我的数组中随机选择一个字符串,但不能两次选择相同的字符串。

string[] names = { "image1.png", "image2.png", "image3.png", "image4.png", "image5.png" };

这可能吗?我正在考虑使用

return strings[random.Next(strings.Length)];

但这有可能两次返回相同的字符串。还是我错了?我是否应该使用List 之类的其他东西来完成此操作。欢迎任何反馈。

【问题讨论】:

  • 听起来你想shuffle 数组,然后正常遍历数组。 Stack Overflow 上有很多乱七八糟的问题。
  • @Atrljoe - 你明白返回相同的字符串两次是随机结果吧?如果您不想两次获得相同的结果,则不能将其描述为随机结果。
  • @Ramhound 当然是随机的。它不会是一系列独立事件,但它仍然是随机的。
  • @ramhound 我理解它不是完全随机的,但在这种情况下,如果我要求用户选择一张图片,它会随机返回所有相同的图片(非常不可能,但理论上可能)那么用户别无选择。我不需要它完美到足以让我看到随机的结果。
  • 我已经回答了这个[来自数组的随机项][1] [1]:stackoverflow.com/questions/1392819/…

标签: c# arrays string random


【解决方案1】:

最简单的方法(但对于大型列表来说很慢)是使用像List 这样的可调整大小的容器,并在选择元素后删除它。喜欢:

var names = new List<string> { "image1.png", "image2.png", "image3.png", "image4.png", "image5.png" };

int index = random.Next(names.Count);
var name = names[index];
names.RemoveAt(index);
return name;

当您的列表为空时,所有值都被选中。

一种更快的方法(特别是如果您的列表很长)是在您的列表中使用洗牌算法。然后,您可以一次弹出一个值。它会更快,因为从List 的末尾删除通常比从中间删除要快得多。至于洗牌,你可以看看this question了解更多详情。

【讨论】:

  • @samb8s 是的,但我更快:)
  • 请注意,如果列表很长,这可能是个坏主意。从长列表的开头附近删除一个项目必须移动它之后的所有项目。
【解决方案2】:

试试下面这段代码

string[] Titles = { "Excellent", "Good", "Super", "REALLY GOOD DOCTOR!", "THANK YOU!", "THE BEST", "EXCELLENT PHYSICIAN", "EXCELLENT DOCTOR" };

comments_title.Value=Titles[new Random().Next(0,Titles.Length) ] ;

【讨论】:

  • 以后,请尝试在您的帖子中添加更多描述。不过好主意! :)
  • 我一直认为所有的cmet都是诚实的,不是自动化的,那些收到好评的实际上是好的。
  • 如果它选择最大值(Titles.Length),这将导致 IndexOutOfRangeException。否则效果很好。 (只需执行 Titles.Length - 1)
  • @Gober 上限是独占的,所以不会有问题:msdn.microsoft.com/en-us/library/2dx6wyd4(v=vs.110).aspx
  • 为什么我生成的总是给我相同的号码? dotnetfiddle.net/1C9CcL
【解决方案3】:

您可以在第一步中打乱数组,然后简单地遍历打乱的数组。
与基于 RemoveAt 的实现的 O(n^2) 相比,这具有 O(n) 的优势。当然,这对于短数组来说并不重要。

检查 Jon Skeet 对以下问题的回答是否有良好的(所有订单都同样可能)实施 shuffle:Is using Random and OrderBy a good shuffle algorithm?

【讨论】:

    【解决方案4】:

    最好的办法就是创建一个重复列表,然后当你随机挑选一个字符串时,你可以将它从重复列表中删除,这样你就不会选择两次了。

    【讨论】:

      【解决方案5】:

      你可以使用的逻辑如下:

      1) 在等于数组长度的范围内选择一个随机整数。您可以使用 System.Random 类来做到这一点。

      2) 使用该数组索引对应的字符串

      3) 从数组中删除具有该索引的项目(使用列表可能更容易)

      然后您可以再次选择,并且不会出现相同的字符串。数组将短一个元素。

      【讨论】:

        【解决方案6】:

        如果您不想/不能修改原始数组,则需要跟踪您使用过的那些,最好在List 中。使用while 循环检查它是否未被使用,然后将其添加到“已使用”列表中。

        【讨论】:

        • 好的,假设原始列表中有 1000 个项目,“已使用”列表中有 999 个项目。您的计划是继续生成随机数,直到达到千分之一?您的列表选择算法将变得越来越慢。对于较长的列表,这是一个糟糕的算法。
        【解决方案7】:
        //SET LOWERLIMIT
        cmd = new SqlCommand("select min(sysid) as lowerlimit from users", cs);
        int _lowerlimit = (int) cmd.ExecuteScalar();
        lowerlimit = _lowerlimit;
        
        //SET UPPERLIMIT
        cmd = new SqlCommand("select max(sysid) as upperlimit from users", cs);
        int _upperlimit = (int) cmd.ExecuteScalar();
        upperlimit = _upperlimit;
        
        //GENERATE RANDOM NUMBER FROM LOWERLIMIT TO UPPERLIMIT
        Random rnd = new Random();
        int randomNumber = rnd.Next(lowerlimit, upperlimit+1);
        
        //DISPLAY OUTPUT
        txt_output.Text += randomNumber;
        

        【讨论】:

          【解决方案8】:

          使用下面的实用方法

          public static class ListExtensions
          {
              public static T PickRandom<T>(this List<T> enumerable)
              {
                  int index = new Random().Next(0, enumerable.Count());
                  return enumerable[index];
              }
          }
          

          然后调用下面的方式

          string[] fruitsArray = { "apple", "orange"};
          string inputString = fruitsArray.ToList().PickRandom();
          

          【讨论】:

            猜你喜欢
            • 2017-01-12
            • 1970-01-01
            • 1970-01-01
            • 2020-10-04
            • 2020-02-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-04-03
            相关资源
            最近更新 更多