从IList <>中选择一个随机元素,而不是这个元素

Rad*_*094 2 c#

我有这种模式,我需要从列表中选择任何随机元素,而不是当前的元素(作为参数传递).我想出了这个方法:

public Element GetAnyoneElseFromTheList(Element el)
{
  Element returnElement = el;
  Random rndElement = new Random();
  if (this.ElementList.Count>2) 
  {
  while (returnElement == el) 
  {
    returnElement = this.ElementList[rndElement.Next(0,this.ElementList.Count)];  
  }

  return returnElement;
  }
 else return null;
}
Run Code Online (Sandbox Code Playgroud)

但是,虽然循环一直困扰着我几天,但我需要睡一会儿.还有其他好办法吗?即.以固定数量的步骤返回的东西?

编辑:在我的情况下,列表保证包含要避免的"el"元素,并且列表不包含重复项,但是看到一些更一般的情况也很有趣.

小智 8

public Element GetAnyoneElseFromTheList(Element el)
{
  if(this.ElementList.Count < 2) return null;
  Random rndElement = new Random();
  int random = rndElement.Next(0,this.ElementList.Count -1);
  if(random >= this.ElementList.indexOf(el)) random += 1;
  return this.ElementList[random];
}
Run Code Online (Sandbox Code Playgroud)

获取0到列表长度减去2之间的随机数.

如果该数字大于或等于元素的索引,则为该数字添加一个.

返回该数字索引处的元素

编辑:在评论中提及的人,然后他们删除了如果你有重复,这不能很好地工作.在这种情况下,最佳解决方案实际上是.

public Element GetAnyoneElseFromTheList(int elId)
{
  if(elId >= this.ElementList.Count) throw new ArgumentException(...)
  if(this.ElementList.Count < 2) return null;
  Random rndElement = new Random();
  int random = rndElement.Next(0,this.ElementList.Count -1);
  if(random >= elId) random += 1;
  return this.ElementList[random];
}
Run Code Online (Sandbox Code Playgroud)

编辑2:重复元素的另一种替代方法是,您可以对列表的克隆版本使用优化的随机排序(随机排序)操作,然后通过列表进行操作.foreach将迭代到列表中的重复元素的数量.这一切都归结为你的随机算法的优化程度.


小智 7

public Element GetAnyoneElseFromTheList(Element el)
{
  Random rndElement = new Random();
  int index;
  if (this.ElementList.Count>1) 
  {
     index = rndElement.Next(0,this.ElementList.Count-1);
     if (this.ElementList[index] == el)
        return this.ElementList[this.ElementList.Count-1];
     else
        return this.ElementList[index];
  }
 else return null;
}
Run Code Online (Sandbox Code Playgroud)